【问题标题】:Row Wise Mode in data.table Rdata.table R 中的逐行模式
【发布时间】:2018-10-27 00:52:57
【问题描述】:

我正在尝试找到一种有效的方法来在 data.table 中的列子集上获取逐行模式

#Sample data    
a <- data.frame( 
        id=letters[], 
        dattyp1 = sample( 1:2, 26, replace=T) , 
        dattyp2 = sample( 1:2, 26, replace=T) , 
        dattyp3 = sample( 1:2, 26, replace=T) ,
        dattyp4 = sample( 1:2, 26, replace=T) , 
        dattyp5 = sample( 1:2, 26, replace=T) , 
        dattyp6 = sample( 1:2, 26, replace=T)
        )

    library(modeest)
    library(data.table)

我从:To find "row wise" "Mode" of a given data in R 知道我可以这样做:

Mode <- function(x) {
     ux <- unique(x)
          ux[which.max(tabulate(match(x, ux)))]
    }   

apply(a[ ,paste0("dattyp",1:6)], 1, Mode)

但这真的很慢(超过我的数百万条记录)。我认为必须有一种方法可以使用 .SDcols 来做到这一点 - 但这确实是按列模式而不是按行。

a<- data.table( a )
    a[ , lapply(.SD , mfv ), .SDcols=c(paste0("dattyp",1:6) ) ]

【问题讨论】:

  • 这个例子——6 个二进制整数列,约 1e7 行——是否代表了您的实际数据集?最佳解决方案可能会因列类型、(即整数可以以与字符串不同的方式处理)、列数、基数和行数而有所不同。 (我快速尝试了一下,想不出比你原来的解决方案更快的方法,而且 fwiw,modeest::mfv() 似乎比用户定义的函数 Mode() 慢)跨度>
  • 我同意,mfv 比 OP 定义的模式函数慢。

标签: r data.table mode


【解决方案1】:

我认为通过 最快的方法仍然是转换为关系(即长)格式并聚合,然后在reldtMtd 函数中找到最大值,如下所示。我想知道使用 Rcpp 会不会更快。

数据:

library(data.table)
M <- 1e6
popn <- 2
set.seed(0L)
a <- data.frame( 
    id=1:M, 
    dattyp1 = sample(popn, M, replace=TRUE), 
    dattyp2 = sample(popn, M, replace=TRUE), 
    dattyp3 = sample(popn, M, replace=TRUE),
    dattyp4 = sample(popn, M, replace=TRUE), 
    dattyp5 = sample(popn, M, replace=TRUE), 
    dattyp6 = sample(popn, M, replace=TRUE)
)    
setDT(a)

方法:

reldtMtd <- function() {
    melt(a, id.vars="id")[, 
        .N, by=.(id, value)][,
            value[which.max(N)], by=.(id)] 
}

#from https://stackoverflow.com/a/8189441/1989480
Mode <- compiler::cmpfun(function(x) {   
    ux <- unique(x)
    ux[which.max(tabulate(match(x, ux)))]
})
Mode2 <- compiler::cmpfun(function(x) names(which.max(table(x))))
matA <- as.matrix(a[, -1L])

baseMtd1 <- function() apply(matA, 1, Mode)
baseMtd2 <- function() apply(matA, 1, Mode2)

library(microbenchmark)
microbenchmark(reldtMtd(), baseMtd1(), baseMtd2(), times=3L)

时间安排:

Unit: seconds
       expr        min         lq       mean     median         uq       max neval
 reldtMtd()   1.882783   1.947515   2.031767   2.012248   2.106259   2.20027     3
 baseMtd1()  15.618716  15.675314  15.809277  15.731913  15.904557  16.07720     3
 baseMtd2() 160.837513 161.692634 162.455048 162.547755 163.263816 163.97988     3

【讨论】:

    【解决方案2】:

    你可以试试这个——虽然我不确定它会快多少。注意,我正在抓取 mfv 返回的第一个数字。

    library(modeest)
    library(data.table)
    
    a <- data.frame( 
      id=letters[], 
      dattyp1 = sample( 1:2, 26, replace=T) , 
      dattyp2 = sample( 1:2, 26, replace=T) , 
      dattyp3 = sample( 1:2, 26, replace=T) ,
      dattyp4 = sample( 1:2, 26, replace=T) , 
      dattyp5 = sample( 1:2, 26, replace=T) , 
      dattyp6 = sample( 1:2, 26, replace=T)
    )
    
    
    a<- data.table( a )
    
    a[ , Mode:=mfv(c(dattyp1,dattyp2,dattyp3,dattyp4,dattyp5,dattyp6))[1],by=id ]
    

    数据表可能会更快。 申请:

    microbenchmark(apply={
    +   apply(a[ ,paste0("dattyp",1:6)], 1, Mode)
    + })
    Unit: microseconds
      expr     min      lq     mean  median      uq      max neval
     apply 574.025 591.803 1056.807 624.988 704.396 39236.79   100
    

    数据表:

    microbenchmark({
    +   a[ , Mode:=mfv(c(dattyp1,dattyp2,dattyp3,dattyp4,dattyp5,dattyp6))[1],by=id ]
    + })
    Unit: milliseconds
                                                                                                           expr     min       lq
     {     a[, `:=`(Mode, mfv(c(dattyp1, dattyp2, dattyp3, dattyp4,          dattyp5, dattyp6))[1]), by = id] } 2.44109 2.748053
         mean   median       uq      max neval
     3.049809 2.898769 3.139559 6.398032   100
    

    【讨论】:

    • 具有 26 行和 6 列的基准可以适当地测量开销。对于超过 1 M 行的用例,它不能被认真地视为方法的有效比较。
    猜你喜欢
    • 2018-08-13
    • 2020-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-12
    • 1970-01-01
    • 2014-02-12
    • 1970-01-01
    相关资源
    最近更新 更多