【问题标题】:How can I speed up this row-by-row operation in data.table如何加快 data.table 中的逐行操作
【发布时间】:2013-07-01 15:33:07
【问题描述】:

我有一个 data.table xe5 行和大约 100 列。我正在寻找前 3 列索引,使得该值不是 NA 或 0。

m <- matrix(rep(NA_integer_, 1e6), ncol=10)
for(i in 1:nrow(m)){
    set.seed(i);
    m[i, sample(1:10, 5)] =  1L:5L
}
DT <- data.table(m);
DT
        V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
     1: NA  5  1  2  3 NA  4 NA NA  NA
     2: NA  1 NA NA  3  5  2 NA NA   4
     3: NA  1  4  3 NA NA NA  2  5  NA
     4:  2  4  3 NA  5  1 NA NA NA  NA
     5:  5  4  1 NA NA NA  2  3 NA  NA
    ---                               
 99996: NA NA  2  3  5  1 NA NA  4  NA
 99997:  2 NA NA NA  1 NA NA  3  5   4
 99998:  5 NA  4  2 NA  1  3 NA NA  NA
 99999: NA  5 NA  1 NA  4 NA  2 NA   3
100000:  5 NA NA NA  2  3  1 NA NA   4

f <- function(x){return(list(which(!is.na(x) & x!=0L)[1:3L]))}

#Here is what apply do
system.time(test <- apply(m, FUN=f, MAR=1))
utilisateur     système      écoulé 
       1.30        0.00        1.29

我发现它很慢,这可能不是data.table 的任务,我正在寻找一种快速获得此答案的方法(欢迎任何方法)。

【问题讨论】:

    标签: r matrix data.table


    【解决方案1】:

    首先,您可以使用0 /0 是NaN 的事实,这也将为is.na 提供TRUE。这将减少到一个!is.na 的条件。其次,您可以使用which 和arr.ind = TRUE 进行矢量化,这将给出row 和col 索引。我们可以用它来除以row 并得到前三个col 值如下:

    system.time(tt <- data.table(which(!is.na(DT[, lapply(.SD, function(x) x/0)]), 
                 arr.ind=TRUE), key="row")[, col[1:3], by="row"])
       user  system elapsed
      0.360   0.000   0.359
    

    编辑:另一种方式:

    DT <- DT[, lapply(.SD, function(x) !is.na(x/0))]
    out <- data.table(matrix(numeric(3e5), ncol=3))
    system.time({    
    for (i in as.integer(seq_along(DT))) {
        for (j in 1:3) {
            zeros <- .subset2(DT, i) & (out[[j]] == 0)
            out[zeros, names(out)[j] := i]
            DT[zeros, c(names(DT)[i]) := FALSE]
        }
    }
    })
    

    不确定它是否是最快的。

    【讨论】:

    • 第一个在我的电脑上更快
    • 去掉 arrayInd 绒毛将使第一个解决方案的时间减少约 25% - t = which(!is.na(m/0)); n = nrow(m); data.table(row = (t-1L) %% n + 1L, col = (t-1L) %/% n + 1L, key = 'row')[, col[1:3], by = row]
    • 很酷,谢谢,当apply(,MAR=1) 比data.table[,,by='row'] 快时,我仍然无法确定规则
    • @statquant apply 将 data.frame (data.table) 强制转换为矩阵,我认为内存问题会在 by = row 变得更快之前出现
    • 在我的真实案例 (3e5*201) 中,替代方式是最快的,不过 >15 秒
    猜你喜欢
    • 1970-01-01
    • 2014-02-12
    • 1970-01-01
    • 1970-01-01
    • 2011-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-22
    相关资源
    最近更新 更多