【问题标题】:Selecting frequent values from multiple columns from R table从 R 表的多列中选择频繁值
【发布时间】:2015-06-23 12:22:25
【问题描述】:

我有一个data.tableres,其数据如下:

            V1 V2 V3 V4
  1:     Day_1  4  4  4
  2:     Day_2  1  1  2
  3:     Day_3  4  5  4
  4:     Day_4  3  4  4
  5:     Day_5  3  2  3

我需要从 V2、V3 和 V4 列组合中选择最频繁的值。也就是说,我需要选择结果如下:

Day_1 4
Day_2 1
Day_3 4
Day_4 4
Day_5 3

我不希望有任何联系,因为总会有奇数列。是否可以操纵data.table 来做到这一点?还是应该修改其他数据类型?

谢谢-V

【问题讨论】:

  • This 可能是您正在寻找的功能。
  • 从链接尝试apply(res[,-1, with=FALSE], 1, Mode) (Mode)
  • @akrun 我会尝试DT[, .(res = Mode(unlist(.SD))), by = V1]
  • @DavidArenburg 您可以将其发布为答案。
  • @Frank 你的代码在 OPs 数据上给出了不正确的结果。

标签: r data.table


【解决方案1】:

我将此作为this old questiondata.table 版本发布,直到提供更好的东西

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

DT[, .(res = Mode(unlist(.SD))), by = V1]

#       V1 res
# 1: Day_1   4
# 2: Day_2   1
# 3: Day_3   4
# 4: Day_4   4
# 5: Day_5   3

【讨论】:

  • @David...谢谢。我会再等一会儿再接受答案。
【解决方案2】:

转换为长格式,然后就很简单了:

dt <- data.table(id=paste("Day",1:5,sep="_"),V2=c(4,1,4,3,3),V3=c(4,1,5,4,2),V4=c(4,2,4,4,3))

melt(dt, id.vars = 'id')[, .N, by = .(id, value)][, value[which.max(N)], by = id]
#      id V1
#1: Day_1  4
#2: Day_2  1
#3: Day_3  4
#4: Day_4  4
#5: Day_5  3

到目前为止,这比其他选项快得多,只要唯一 (id,value) 对的数量不太大。

【讨论】:

    【解决方案3】:

    以下是大卫回答的两种变体:

    # table
    DT[,ans:={
        tab <- table( r = rep(.I,length(.SD)), unlist(.SD) )
        as( colnames(tab)[ max.col(tab) ], class(.SD[[1]]) )
    },.SDcols=-1]
    
    # apply Mode
    DT[,ans:=apply(.SD,1,Mode),.SDcols=-1]
    

    我想我会看看这些,因为按行拆分 DT 可能会很慢。

    速度

    与逐行比较。从很少的唯一值和行开始...

    n  <- 1e4
    nv <- 5
    nc <- 3
    
    DT <- do.call(data.table,c(
      list(id=1:n),
      replicate(nc,sample(nv,n,replace=TRUE),simplify=FALSE)
    ))
    
    require(rbenchmark)
    
    benchmark(
      table     = DT[,.({
        tab <- table( r = rep(.I,length(.SD)), unlist(.SD) )
        as( colnames(tab)[ max.col(tab) ], class(.SD[[1]]) )
      }),.SDcols=-1],
      byMode    = DT[,.(Mode(unlist(.SD))), by = id],
      applyMode = DT[,.(apply(.SD,1,Mode)),.SDcols=-1],
      replications=10
    )[1:5]
    #        test replications elapsed relative user.self
    # 3 applyMode           10    1.66    4.611      1.65
    # 2    byMode           10    2.03    5.639      2.02
    # 1     table           10    0.36    1.000      0.36
    

    分别增加三个参数中的每一个...

    nv <- 1e3 # up from 5
    
    #        test replications elapsed relative user.self
    # 3 applyMode           10    1.67    1.000      1.67
    # 2    byMode           10    2.05    1.228      2.02
    # 1     table           10    4.27    2.557      4.15
    
    n  <- 5e4 # up from 1e4
    
    #        test replications elapsed relative user.self
    # 3 applyMode           10    8.67    4.492      8.65
    # 2    byMode           10   10.21    5.290     10.22
    # 1     table           10    1.93    1.000      1.92
    
    nc <- 100 # up from 3
    
    #        test replications elapsed relative user.self
    # 3 applyMode           10    2.59    1.000      2.59
    # 2    byMode           10    6.71    2.591      6.69
    # 1     table           10   11.69    4.514     11.68
    

    讨论。 (我正在比较基准测试中的 elapsed 列。)

    • nv. 虽然table 在小情况下胜出,但随着唯一值的数量,它的扩展性很差,因为它的tab 对象变得非常大。其他两种方法不受影响。
    • n。一切都随着行数线性缩放。 (我预计 table 在这个维度上的扩展也更糟,但也许 n 需要更大。)
    • nctable 也随列线性缩放,而其他两个做得更好。

    再次,融化

    # back to original values for n, nv, nc
    benchmark(
      table     = DT[,.({
        tab <- table( r = rep(.I,length(.SD)), unlist(.SD) )
        as( colnames(tab)[ max.col(tab) ], class(.SD[[1]]) )
      }),.SDcols=-1],
      byMode    = DT[,.(Mode(unlist(.SD))), by = id],
      applyMode = DT[,.(apply(.SD,1,Mode)),.SDcols=-1],
      melt      = melt(DT, id.vars = 'id')[, .N, by = .(id, value)][, 
                    value[which.max(N)], by = id],
      melto     = melt(DT, id.vars = 'id')[, .N, by = .(id, value)][
                    order(N)][,last(value),by=id],
      meltMode  = melt(DT, id.vars = 'id')[,Mode(value),by=id],
      replications=10
    )[1:5]
    #        test replications elapsed relative user.self
    # 3 applyMode           10    2.42    8.643      2.36
    # 2    byMode           10    2.84   10.143      2.81
    # 4      melt           10    0.28    1.000      0.28
    # 6  meltMode           10    1.92    6.857      1.81
    # 5     melto           10    0.44    1.571      0.44
    # 1     table           10    0.83    2.964      0.81
    

    看起来像 @eddi 的 meltwhich.max 获胜。

    数据

    DT <- 
      data.table(V1=paste("Day",1:5,sep="_"),V2=c(4,1,4,3,3),V3=c(4,1,5,4,2),V4=c(4,2,4,4,3))
    

    【讨论】:

      猜你喜欢
      • 2011-03-07
      • 2022-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-27
      • 1970-01-01
      相关资源
      最近更新 更多