如何通过引用更新`foreach`中的`data.table`

时间:2017-09-27 08:18:01

标签: r data.table parallel-foreach

我使用.csvdata.table个大文件读入fread。在下一步中,我会执行一些数据清理操作,例如将某些字符变量转换为日期。

内存优化解决方案

这是我在MWE中的内存优化解决方案:

library(data.table)
library(foreach)

dt <- data.table(chr_date_1 = c("2017-01-01", "2017-01-02", "2017-01-03"),
                 chr_date_2 = c("2017-01-04", "2017-01-05", "2017-01-06"))

for (date_var in c("chr_date_1", "chr_date_2")) {
  dt %>% 
    set(j = date_var, value = ymd(.[[date_var]]))
}

速度优化解决方案?

由于有850万个观测值和~30个应该以某种方式操纵的变量,我想知道这是否可以使用foreach在速度方面进行优化。 (我在具有128GB RAM的虚拟客户端上运行R,因此内存不是主要问题。)我的第一次尝试看起来像这样:

registerDoParallel(cores=7)

foreach (date_var = names(dt), .packages = c("data.table")) %dopar% {
  set(dt, j = date_var, value = as.Date(dt[[date_var]]))
}

不幸的是,这只会在控制台中打印结果,而不是更新dt

[[1]]
chr_date_1 chr_date_2
1: 2017-01-01 2017-01-04
2: 2017-01-02 2017-01-05
3: 2017-01-03 2017-01-06

[[2]]
chr_date_1 chr_date_2
1: 2017-01-01 2017-01-04
2: 2017-01-02 2017-01-05
3: 2017-01-03 2017-01-06

接下来,我尝试设置.combine.init,...

foreach (date_var = names(dt), .packages = c("data.table"),
         .combine = "cbind", .init = dt) %dopar% {
           set(dt, j = date_var, value = as.Date(dt[[date_var]]))
         }

...但是添加了新列而不是更新现有列:

  chr_date_1 chr_date_2 chr_date_1 chr_date_2 chr_date_1 chr_date_2
  1: 2017-01-01 2017-01-04 2017-01-01 2017-01-04 2017-01-01 2017-01-04
  2: 2017-01-02 2017-01-05 2017-01-02 2017-01-05 2017-01-02 2017-01-05
  3: 2017-01-03 2017-01-06 2017-01-03 2017-01-06 2017-01-03 2017-01-06

那么,是否可以使用data.table并行更新foreach的多个列?

如果没有,可能有一个解决方案,我并行创建所有新列,并以某种方式将它们合并到现有的data.table?阻止我详细说明这一点的一个方面是,当我省略foreach时,最后.init = dt剪切产生相同的( 4列)。

编辑:

我找到了获得所需结果的方法,但在一个包含7个变量(=已注册核心数)和3M观察值的示例中,这比内存优化解决方案长约5倍。所以只是告诉你,如何做到这一点:

result <- foreach (date_var = names(dt), .packages = c("data.table")) %dopar% {
    dt[, (date_var) := lapply(.SD, as.Date, format = "%Y-%m-%d"), .SDcols = date_var]
  } %>% .[[length(.)]]

此外,所需的内存量是疯狂的。

0 个答案:

没有答案