【问题标题】:Row maximum in data table数据表中的最大行数
【发布时间】:2015-02-12 19:56:20
【问题描述】:

我在 data.table 中有一个包含 8,000,000 行和 100 列的数据集,其中每列都是一个计数。我需要找到每行的最大计数以及该最大值在哪一列。

我可以使用

快速获取每行的最大值是哪一列
dt <- dt[, maxCol := which.max(.SD), by=pmxid]

但试图获得实际的最大值使用

dt <- dt[, nmax := max(.SD), by=pmxid]

非常慢。我运行了将近 20 分钟,只计算了 200,000 行最大值。找到最大列大约需要。所有 8,000,000 行需要 2 分钟。

为什么要花这么长时间才能找到最大值?时间不应该和which.max()一样或者更少吗?

【问题讨论】:

  • 这实际上是一个有趣的问题,因为max 是原始函数,应该非常高效。不过,如果您能提供一些最低限度的可重现示例,那就太好了。另外,pmxid 只是一个行号吗?一般来说,data.table 在用于每行操作时没有太大优势。
  • @mattdevlin max.col from base R 非常快。 indx &lt;- max.col(df, ties.method='first'); df[cbind(1:nrow(df), indx)] 获取每行的最大值
  • @DavidArenburg: pmxid 只是一个数字 id,但它们与行号不匹配
  • 你写了“我可以快速得到哪一列的最大值每一行使用...”
  • 如果您只需要一个新列,则不需要 dt &lt;- dt[,x:=y,by=z] 中的 &lt;- 分配。您可能想查看包的介绍材料:github.com/Rdatatable/data.table/wiki/Getting-started

标签: r data.table


【解决方案1】:

虽然,您正在寻找 data.table 解决方案,但这里有一个 base R 解决方案,它对于您的数据集来说已经足够快了。

indx <- max.col(df, ties.method='first')
df[cbind(1:nrow(df), indx)]

在稍微大一点的数据集上,system.time 比较显示

system.time({
 indx <- max.col(df1, ties.method='first')
 res <- df1[cbind(1:nrow(df1), indx)]
})
#   user  system elapsed 
# 2.180   0.163   2.345 



df1$pmxid <- 1:nrow(df1)
dt <- as.data.table(df1)
system.time(dt[, nmax:= max(.SD), by= pmxid])
#      user   system  elapsed 
#1265.792    2.305 1267.836 

base R 方法比帖子中的data.table 方法更快。

数据

set.seed(24)
df <- as.data.frame(matrix(sample(c(NA,0:20), 20*10, 
       replace=TRUE), ncol=10))
#if there are NAs, change it to lowest number
df[is.na(df)] <- -999

set.seed(585)
df1 <- as.data.frame(matrix(sample(c(NA,0:20), 100*1e6,
 replace=TRUE), ncol=100))
df1[is.na(df1)] <- -999

【讨论】:

  • 优秀。我的数据集需要 21.28 秒!
  • @mattdevlin 问题的标题和代码涉及data.tables,而这个答案没有。你想概括你的问题吗?您甚至可以考虑使用矩阵而不是 dfdt...我怀疑这些操作会更快。
  • 对于矩阵输入,来自matrixStatscolMaxs 相当快。
  • 哦,我明白了。答案没有提到 data.tables 不合适,所以我错过了这一点。我想@akrun 有责任在答案中澄清。 :)
  • @Frank 也用system.time 更新了 data.table 方法的帖子。感谢您的 cmets。
【解决方案2】:

对于 data.table 中的最大列数,

dt[, max:= do.call(pmax, .SD)]

dt[, nmax:= max(.SD), by= 1:nrow(dt)]快很多,比上面的base R解决方案还要快:

library(data.table)
 
ncols=100
nrows=8000000
 
dfi <- as.data.frame(matrix(runif(ncols*nrows), ncol = ncols, nrow = nrows))
 
df=dfi
system.time({
 indx <- max.col(df, ties.method='first')
 df$max <- df[cbind(1:nrow(df1), indx)]
 })
#   user  system elapsed 
#   8.89    1.37   10.45 

dt <- as.data.table(dfi)
system.time({
 dt[, max:= do.call(pmax, .SD)]
 })
#   user  system elapsed 
#   3.31    0.01    3.33

【讨论】:

    【解决方案3】:
    1. 计算 Colmax 索引后,使用该索引检索每行中的最大值
    dt[Colmax == <value>] 
    

    或者,

    dt[J(<values>), on = 'Colmax']
    
    1. 另外,语法错误
    dt[, nmax := max(.SD), by = pmxid]
    

    这会整理nrow(dt) * length(.SD) 长度的向量(请参阅ma​​x() 说明中的注意

    改为尝试:

    dt[, nmax := apply(.SD, 1, max), by = pmxid]
    

    或者,并行最大值:

    dt[, nmax := pmax(.SD), by = pmxid]
    

    【讨论】:

      猜你喜欢
      • 2014-07-08
      • 2010-11-16
      • 2010-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-12
      • 2013-04-13
      相关资源
      最近更新 更多