问题描述
我在一个较大的数据集(> 20GB)上运行了一个分组,但似乎运行不正常
这是我的代码
mydf[,.(value = n_distinct(list_of_id,na.rm = T)),by = .(week),keep = c("list_of_id","week")
]
它返回了此错误
警告消息:1:在serialize(数据,node $ con)中:
加载2时,“ package:MLmetrics”可能不可用 serialize(data,node $ con):'package:MLmetrics'可能不可用 加载3时:在serialize(data,node $ con)中:'package:MLmetrics' 加载4时可能不可用:在serialize(data,node $ con)中:
加载5:输入“ package:MLmetrics”时可能不可用 serialize(data,node $ con):'package:MLmetrics'可能不可用 加载6时:在serialize(data,node $ con)中:'package:MLmetrics' 加载7时可能不可用:在serialize(data,node $ con)中:
加载8:输入时,“ package:MLmetrics”可能不可用 serialize(data,node $ con):'package:MLmetrics'可能不可用 加载时
我最初已加载该库,但随后在运行此代码之前运行remove.packages(MLmetrics)。另外,我检查了flicted :: conflict_scout,并且MLmetrics包没有显示任何冲突。
当我运行这段代码
> mydf %>%
+ filter(week == "2012-01-02")
它给了我这个输出
week value
1: 2012-01-02 483
2: 2012-01-02 61233
我担心在对数据进行分组时出了点问题,因为它没有创建价值周的不同分组。两列都存储为字符数据类型。
解决方法
disk.frame
看起来很有趣,可以填补RAM处理与大数据之间的空白。
为了测试它,我创建了一个200 * 200 Mb CSV文件的集合,总共40Gb,高于计算机上安装的32Gb RAM:
library(furrr)
library(magrittr)
library(data.table)
libray(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,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' t合并和/或完全处理),还有很多Warning messages: 1: In serialize(data,node$con)
。
我在GitHub上提交了一个问题。
在澄清这一点之前,我建议您使用有效的dplyr
语法。
此示例使我相信disk.frame
允许处理supported verbs大于RAM的数据
此处是{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。
如果任何人/组织想为此功能的开发提供资金,请直接与我联系。