优化R语言代码:基于投票数据批量填充政党字段
提速方案:按省份得票比例批量填充Party列
原代码的性能瓶颈集中在嵌套循环、频繁向量拼接(c())和重复子集索引上,针对1300万行的大数据量,以下是几种高效优化方案:
方案1:使用data.table(性能最优,适配超大数据)
data.table的分组操作和内存效率远优于基础R循环,直接按省份批量生成对应比例的party值:
library(data.table) # 转换为data.table格式 setDT(df0) setDT(votes) # 统计每个省份的样本量 prov_counts = df0[, .N, by = geo_prov] # 合并得票比例与样本量,计算每个政党需生成的数量 votes_with_counts = votes[prov_counts, on = "geo_prov"] votes_with_counts[, n := floor(prop * N)] # 按省份批量生成party列表并填充回原数据 df0[, party := votes_with_counts[.SD, on = "geo_prov", rep(party, n), by = .EACHI]$V1]
方案2:使用dplyr(代码易读,适配tidyverse用户)
利用dplyr的分组与批量生成操作,彻底替代循环:
library(dplyr) # 统计每个省份的样本量 prov_counts = df0 %>% count(geo_prov, name = "n_prov") # 生成各省份的party分配列表 vote_assignments = votes %>% left_join(prov_counts, by = "geo_prov") %>% mutate(n = floor(prop * n_prov)) %>% rowwise() %>% mutate(party_list = list(rep(party, n))) %>% ungroup() %>% group_by(geo_prov) %>% summarise(party_all = list(unlist(party_list))) # 合并回原数据并填充 df0 = df0 %>% left_join(vote_assignments, by = "geo_prov") %>% mutate(party = unlist(party_all)) %>% select(-party_all)
方案3:基础R向量化优化(无需额外包)
通过预计算所有省份的分配规则,一次性生成结果:
# 统计每个省份的样本量 prov_counts = table(df0$geo_prov) # 预生成每个省份的party分配向量 party_assignments = lapply(names(prov_counts), function(prov) { n = prov_counts[prov] prov_votes = votes[votes$geo_prov == prov, ] rep(prov_votes$party, floor(prov_votes$prop * n)) }) # 按原数据省份顺序匹配填充 df0$party = unlist(sapply(match(df0$geo_prov, names(prov_counts)), function(i) party_assignments[[i]]))
优化核心逻辑
- 替换嵌套循环:用底层优化的分组操作替代手动循环,大幅提升计算效率
- 减少内存浪费:避免
c()频繁扩容向量的低效操作,一次性生成目标长度的向量 - 消除重复计算:仅计算一次省份样本量与得票比例的匹配,避免原代码中反复的子集索引操作
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

