如何加快每列迭代

时间:2019-04-19 11:17:30

标签: r performance data.table iteration vectorization

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

让我们以mtcar为例

我觉得您可以坚持使用.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()函数...

向量化的解决方案会很好。

3 个答案:

答案 0 :(得分:1)

一种可能的方法:

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

答案 1 :(得分:0)

编辑:这似乎产生与您相同的结果。

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]

答案 2 :(得分:0)

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