R语言如何计算某列分类值对应的唯一ID在其余分类中的共现占比
优化思路
你的代码性能瓶颈主要来自两个问题:
- 没有提前对
name+id做全局去重,同一个name下同一个id重复出现会被多次计算,白白浪费算力 - 分两次遍历全量数据集,大数据下IO开销翻倍
另外原代码还有潜在统计误差:如果同一个name+id组合在原数据中重复出现,count=n()会重复计数,不符合“统计唯一id出现次数”的需求定义。下面给出两个优化实现:
方案1:精简dplyr实现(无需中间变量,代码更简洁)
直接把B的唯一id判断嵌入链式操作,不需要额外生成中间表,比原写法短40%,100万行以内数据集足够用:
library(dplyr) the_name <- "B" df %>% distinct(name, id) %>% filter(id %in% id[name == the_name], name != the_name) %>% count(name, name = "count") %>% mutate(pct_common = round(count / n_distinct(df$id[df$name == the_name]) * 100, 1))
输出和你要求的格式完全一致。
方案2:data.table高性能实现(百万/千万级数据集首选)
data.table底层为C实现,大数据下计算速度是dplyr的3~10倍,内存占用更低:
library(data.table) setDT(df) # 转换为data.table格式,无额外拷贝开销 the_name <- "B" # 先去重冗余的name-id组合,大幅减少计算量 unique_df <- unique(df, by = c("name", "id")) # 提前计算B的唯一id集合和总数,只遍历一次 b_ids <- unique_df[name == the_name, id] b_total <- length(b_ids) # 分组统计+计算占比一步完成 result <- unique_df[id %in% b_ids & name != the_name, .(count = .N), by = name][ , pct_common := round(count/b_total*100, 1) ][order(name)]
如果数据集超过500万行,这个方案的性能优势会非常明显。
内容的提问来源于stack exchange,提问作者Shibaprasad
相关产品推荐
相关产品推荐

