如何使用 data.table 根据条件计算列总和?

How can you calculate column sums based on a condition using data.table?

我有一个 table 个 ID 和 1000 列随机值。我想对 ID 进行分组并计算每列小于 0.01 的值的数量。

我使用循环迭代合并 table,但必须使用 evalparse 访问列名。不幸的是 运行 花费的时间太长了。我过去曾针对不同的问题实施过类似的 for 循环,因此我知道迭代合并不会花费那么长时间。我认为 evalparse 是减慢代码速度的原因。有没有办法不使用这些功能就可以做到这一点?

library(data.table)
set.seed(1)
data <- data.table(ID = rep(LETTERS[1:3], 13), 
  col1 = rnorm(39), 
  col2 = rnorm(39), 
  col3 = rnorm(39))

我需要为每一列生成以下内容:data[,sum(col1 < 0.01)]; data[,sum(col2 < 0.01)]; data[,sum(col3 < 0.01)]

columns <- colnames(data)[2:ncol(data)]
d <- data[,.N, keyby = ID][,N := NULL]
for (col in 1:length(columns)) {
    sum_table <-  data[, sum(eval(parse(text = ..columns[col])) < 0.01), by = ID]
d <- d[sum_table]
}

我希望能够在不使用 evalparse 的情况下重现此内容,因此 运行 时间更快。

我们可以在 .SDcols 中指定感兴趣的列后使用 lapply 循环遍历 Data.table (.SD) 的子集并获取元素的数量小于 0.01

data[, lapply(.SD,  function(x) sum(x < 0.01)), .SDcols = col1:col3]

或者将.SD转换为逻辑矩阵得到colSums

data[, colSums(.SD < 0.01), .SDcols = col1:col3]

如果有分组变量,还要指定by

data[, lapply(.SD,  function(x) sum(x < 0.01)), .SDcols = col1:col3, by = ID]
data[, as.list(colSums(.SD < 0.01)), .SDcols = col1:col3, by = ID]