0

我在一个大型数据集(> 20GB)上运行了一个分组,但它似乎工作不正常

这是我的代码

mydf[, .(value = n_distinct(list_of_id, na.rm = T)),
                      by = .(week),
                      keep = c("list_of_id", "week")
                      ] 

它返回了这个错误

警告消息:1:在 serialize(data, node$con) 中:
“package:MLmetrics”在加载时可能不可用 2:在 serialize(data, node$con) 中:“package:MLmetrics”在加载时可能不可用 3 : 在 serialize(data, node$con) 中: 'package:MLmetrics' 可能在加载时不可用 4: 在 serialize(data, node$con) 中:
'package:MLmetrics' 在加载时可能不可用 5: 在 serialize( data, node$con) : 'package:MLmetrics' 可能在加载时不可用 6: 在 serialize(data, node$con) : 'package:MLmetrics' 可能在加载时不可用 7: 在 serialize(data, node$ con) :
'package:MLmetrics' 可能在加载时不可用 8: In serialize(data, node$con) : 'package:MLmetrics' 可能在加载时不可用

我最初加载了库,但在运行此代码之前我运行了 remove.packages(MLmetrics)。此外,我检查了 conflicted::conflict_scout 并没有与包 MLmetrics 出现任何冲突。

当我运行这段代码

> mydf %>% 
+   filter(week == "2012-01-02")

它给了我这个输出

         week    value 
1: 2012-01-02      483     
2: 2012-01-02     61233  

我担心在对数据进行分组时出现问题,因为它没有创建价值周的不同组。两列都存储为数据类型字符。

4

2 回答 2

4

disk.frame填补 RAM 处理和大数据之间的空白看起来很有趣。

为了测试它,我创建了一个 200 * 200 Mb CSV 文件的集合,总大小为 40Gb,高于我计算机上安装的 32Gb RAM:

library(furrr)
library(magrittr)
library(data.table)
library(dplyr)
library(disk.frame)
plan(multisession,workers = 11)
nbrOfWorkers()
#[1] 11

filelength <- 1e7

# Create 200 files * 200Mb
sizelist <- 1:200 %>% future_map(~{
  mydf <- data.table(week = sample(1:52,filelength,replace=T),
                     list_of_id=sample(1:filelength,filelength,replace=T))
  filename <- paste0('data/test',.x,'.csv')
  data.table::fwrite(mydf, filename)
  ##write.csv(mydf,file=filename)
  file.size(filename)
})

sum(unlist(sizelist))
# [1] 43209467799

作为distinct_n一个dplyr动词,我首先停留在dplyr语法上:

setup_disk.frame()
#The number of workers available for disk.frame is 6
options(future.globals.maxSize = Inf)

mydf = csv_to_disk.frame(file.path('data',list.files('data')))
"
csv_to_disk.frame: Reading multiple input files.
Please use `colClasses = `  to set column types to minimize the chance of a failed read
=================================================

 ----------------------------------------------------- 
-- Converting CSVs to disk.frame -- Stage 1 of 2:

Converting 200 CSVs to 60 disk.frames each consisting of 60 chunks

 Progress: ──────────────────────────────────────────────────────────────── 100%

-- Converting CSVs to disk.frame -- Stage 1 or 2 took: 00:01:44 elapsed (0.130s cpu)
 ----------------------------------------------------- 
 
 ----------------------------------------------------- 
-- Converting CSVs to disk.frame -- Stage 2 of 2:

Row-binding the 60 disk.frames together to form one large disk.frame:
Creating the disk.frame at c:\TempWin\RtmpkNkY9H\file398469c42f1b.df

Appending disk.frames: 
 Progress: ──────────────────────────────────────────────────────────────── 100%

Stage 2 of 2 took: 59.9s elapsed (0.370s cpu)
 ----------------------------------------------------- 
Stage 1 & 2 in total took: 00:02:44 elapsed (0.500s cpu)"


result <- mydf %>% 
  group_by(week) %>% 
  summarize(value = n_distinct(list_of_id)) %>% 
  collect  

result
# A tibble: 52 x 2
    week   value
   <int>   <int>
 1     1 9786175
 2     2 9786479
 3     3 9786222
 4     4 9785997
 5     5 9785833
 6     6 9786013
 7     7 9786586
 8     8 9786029
 9     9 9785674
10    10 9786314
# ... with 42 more rows

所以它有效!用于此特定任务的总 RAM 内存在 1 到 5Gb 之间波动,在 6 个处理器上处理 20 亿行所需的时间不到 10 分钟,限制因素似乎是磁盘访问速度而不是处理器性能。

我还测试了data.table语法,因为disk.frame两者都接受,但是我返回的速度太快了 60 倍多的行(好像从 200 个 CSV 中创建的 60 个 disk.frames 没有合并和/或完全处理),还有很多Warning messages: 1: In serialize(data, node$con).

我在GitHub 上提交了一个问题。
在澄清这一点之前,我建议保留dplyr有效的语法。

这个例子让我相信,允许为支持的动词disk.frame处理大于 RAM 的数据

于 2020-09-16T23:19:59.617 回答
3

{disk.frame} 的作者在这里。

问题是目前, {disk.frame} 没有按within每个块分组。它不像 dplyr 语法那样进行全局分组。

所以你必须再次总结它才能达到你想要的。所以我建议现在坚持使用 dplyr 语法。

正如@Waldi 指出的那样,{disk.frame}的 dplyr 语法工作正常,并且目前缺少对 data.table 的支持,因此您现在只能使用 dplyr 语法来实现您想要的。

{disk.frame} 需要实现https://github.com/xiaodaigh/disk.frame/issues/239才能适用于 data.table。

如果有人/组织愿意资助此功能的开发,请 DM 我。

于 2020-09-17T01:58:39.597 回答