如何在R中对超大规模计数型数据框抽样避免内存溢出?
解决超大规模加权抽样的内存问题
你的错误根源在于tidyr::uncount(count)这一步:把每个ID按count值展开成对应行数的行后,总数据量达到1013条,远远超过R能处理的向量最大长度(约2×109),直接触发内存溢出和向量超限错误。
根本不需要展开原始数据,直接基于ID的count值作为权重进行抽样即可,以下是两种高效可行的方案:
方案1:用dplyr的slice_sample直接加权抽样
这种方法直观易懂,适合快速实现:
target_size <- 1e12 # 替换成你的目标抽样规模:1e12/1e11等 total_count <- sum(df2$count) df_random[[i]] <- df2 %>% mutate(ID = factor(ID)) %>% # 按count作为权重,有放回抽取target_size个样本 slice_sample(n = target_size, replace = TRUE, weight_by = count) %>% # 统计每个ID的抽样次数 count(ID, name = "value", .drop = FALSE)
方案2:用多项分布直接生成抽样次数(更高效)
当目标抽样规模极大时,直接生成每个ID的抽样次数比逐次抽样更快,核心是利用rmultinom函数基于多项分布计算结果:
target_size <- 1e12 total_count <- sum(df2$count) df_random[[i]] <- df2 %>% mutate( ID = factor(ID), # 计算每个ID的抽样概率 prob = count / total_count ) %>% # 生成每个ID的抽样次数 mutate(value = rmultinom(n = 1, size = target_size, prob = prob)[, 1]) %>% select(ID, value) %>% # 确保所有ID都保留,即使抽样次数为0 tidyr::complete(ID, fill = list(value = 0))
注意事项
- 若需要无放回抽样:当抽样比例极低(比如1%以下),有放回抽样的结果和无放回几乎无差异;若抽样比例较高且必须无放回,可以用
sample(df2$ID, size = target_size, replace = FALSE, prob = df2$count)后再统计频次,但这种方式在target_size极大时速度会比方案2慢。 - 确保
count列的数值类型正确:如果是整数型,转换为numeric后计算概率不会有精度问题。
内容的提问来源于stack exchange,提问作者mel099
相关产品推荐
相关产品推荐

