【问题标题】:How can you calculate column sums based on a condition using data.table?如何使用 data.table 根据条件计算列总和?
【发布时间】:2019-09-19 10:14:18
【问题描述】:

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

我使用循环迭代合并表,但必须使用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 &lt; 0.01)]; data[,sum(col2 &lt; 0.01)]; data[,sum(col3 &lt; 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 的情况下重现此问题,因此运行时间更快。

【问题讨论】:

    标签: r sum data.table conditional multiple-columns


    【解决方案1】:

    .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]
    

    【讨论】:

    • 是的,它又快又简单,效果很好。我在使用data.table 时并不总是考虑lapply
    • Re the by=,你也可以重塑dcast(melt(data, id="ID")[value &lt; 0.01], ID ~ variable) @abbas 如果做很多这样的操作,将数据保持为融化格式可能是有意义的。
    猜你喜欢
    • 2021-08-31
    • 2021-12-07
    • 1970-01-01
    • 2016-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-24
    • 2016-12-05
    相关资源
    最近更新 更多