【问题标题】:How to speed up per column iteration如何加快每列迭代
【发布时间】:2019-09-09 16:13:55
【问题描述】:

我想遍历 data.table 并应用一个函数,该函数需要 data.table 中另一列的信息,有时甚至是多个...

我们以mtcars为例

我觉得您可以坚持使用 .SD 方式,但可以提供额外的参数并提高效率...

require(data.table)
dt = data.table(mtcars)

#looping through columns of mtcars...
cols = c('mpg', 'hp', 'disp')
dt[,lapply(.SD, function(x) x/mean(x)), .SDcols=cols]

# But actually I want to devide x by the mean of x where am==1

# Now I am doing this...

specificMean= function(DT) {
  x = DT$feature
  xAM = DT[AM==1]$feature
  MEAN = mean(xAM, na.rm=TRUE)
  x = x/MEAN    
  return(x)
}

dt[,(cols):=lapply(cols, function(x) specificMean(data.table(feature=get(x), AM=am))), .SDcols=cols]
print(dt)

我觉得这要慢得多,因为它在每次迭代中执行 data.table() 函数...

矢量化解决方案会很好..

【问题讨论】:

    标签: r performance data.table iteration vectorization


    【解决方案1】:

    system.time(dt[,lapply(cols, function(x) specificMean(data.table(feature=get(x), AM=am))), .SDcols=cols])

    用户系统已过 0.010 0.000 0.005

    感谢@chinsoon12,使用两个循环的高效方法

    system.time(dt[,mapply(`/`, .SD[,-"am"], lapply(.SD[am==1, -"am"], mean), SIMPLIFY=FALSE), .SDcols=c("am", cols)])

    用户系统已过 0.001 0.000 0.001

    感谢@Cole,使用一个循环的有效方法

    system.time(dt[,.SD / lapply(.SD[am == 1], mean, na.rm = TRUE), .SDcols = cols])

    用户系统已过 0.001 0.000 0.001

    【讨论】:

    • microbenchmark 是一个运行计时的好库。这表明@chinsoon12 的解决方案更快,因为它的结果以毫秒为单位(或任何最合适的单位)。此外,如果这些是解决方案,您应该选择一个作为答案。
    【解决方案2】:

    编辑:这似乎产生了和你一样的结果。

    library(data.table)
    
    dt = data.table(mtcars)
    cols = c('mpg', 'hp', 'disp')
    
    dt[, (cols) := .SD / lapply(.SD[am == 1], mean, na.rm = TRUE), .SDcols = cols]
    
    

    【讨论】:

    • 对不起 Cole,这不是我的想法...我想遍历 cols 并将每列除以 'am' 等于 1 的列的平均值在您的解决方案中记录仍然在那里是正确的,但由于am == 1 而被排除的所有其他不包括在内,也应除以相同的数字
    • 查看编辑。现在的输出和你的一样,有点像x / mean(x)
    【解决方案3】:

    一种可能的方法:

    dt[, (cols) := mapply(`/`, .SD[,-"am"], lapply(.SD[am==1, -"am"], mean), SIMPLIFY=FALSE), 
        .SDcols=c("am", cols)]
    

    【讨论】:

    • 谢谢@chinsoon12,这是一种更高效、更快捷的方法,虽然语法不简单...
    • 添加摘要 dt 会使其看起来更简单:dt_mean <- dt[am == 1, lapply(.SD, mean, na.rm = TRUE), .SDcols = cols];dt[, mapply('/', .SD, dt_mean), .SDcols = cols]
    • 或者更好的是,使用我的解决方案的方法,因为似乎am.SD 中可用,即使它不在列出的.SDcols 中。这比 Wienand 的原版快 10 倍,比我的快 40%:dt[, mapply('/', .SD, lapply(.SD[am==1,], mean)), .SDcols = cols]
    猜你喜欢
    • 2022-01-23
    • 1970-01-01
    • 2020-12-30
    • 2021-09-17
    • 2021-07-31
    • 2013-12-19
    • 2014-04-27
    • 1970-01-01
    • 2014-10-06
    相关资源
    最近更新 更多