我有一个ID表和1000列随机值。我想对ID进行分组,并为每列计算小于0.01的值数量。
我使用循环来迭代合并表,但是必须使用<errors>
<error>
<code>504</code>
<message>Gateway Timeout</message>
</error>
</errors>
和eval
访问列名。不幸的是,这花费了太长时间。过去,我为不同的问题实现了类似的for循环,因此我知道迭代合并不会花那么长时间。我认为parse
和eval
是使代码运行缓慢的原因。有没有不用这些功能的方法吗?
parse
我需要为每一列生成以下内容: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]
}
和eval
的情况下重现此内容,因此运行时间更快。
答案 0 :(得分:2)
在lapply
中指定感兴趣的列并计算小于0.01的元素数之后,我们可以使用.SD
遍历Data.table(.SDcols
)的子集。
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]