按recid分组计算频率:为DataFrame添加count与freq列的需求
按recid分组统计列值出现次数及频率的R实现
需求说明
需要对DataFrame按recid字段分组,新增4列:
count1:当前行col1值在分组内col1和col2中的总出现次数count2:当前行col2值在分组内col1和col2中的总出现次数Freqcol1:count1除以分组内col1和col2的总元素数Freqcol2:count2除以分组内col1和col2的总元素数
示例:第1行count1为2,因为值10在abc_12分组的两列中共出现2次,Freqcol1为2/4=0.5。
原始DataFrame
df <- data.frame( ID = c(1, 2, 3), col1 = c(10, 10, 10), col2 = c(12, 15, 10), recid = c("abc_12", "abc_12", "def_34") )
期望输出
ID col1 col2 recid count1 count2 Freqcol1 Freqcol2 1 10 12 abc_12 2 1 0.5 0.25 2 10 15 abc_12 2 1 0.5 0.25 3 10 10 def_34 2 2 0.5 0.5
注:原示例中第1、2行的Freqcol2应为1/4=0.25,此处修正数据准确性。
现有代码问题
你提供的代码未按recid分组,且长表转换后的统计逻辑错误,无法得到目标结果:
df %>% pivot_longer(-ID) %>% mutate(count = n(), .by = value) %>% mutate(freq = count / n()) %>% pivot_wider(values_from = c(value, count, freq))
修正后的解决方案
核心思路是先按recid分组统计所有值的出现次数,再将统计结果映射回原表计算频率:
library(dplyr) library(tidyr) df %>% # 按recid分组,合并col1和col2为全值列表并展开 group_by(recid) %>% mutate(temp = list(c(col1, col2))) %>% unnest(temp) %>% # 统计每个值在分组内的总出现次数 count(temp, name = "total_count") %>% # 关联回原数据 right_join(df, by = "recid") %>% # 匹配col1、col2对应的计数,计算频率 mutate( count1 = total_count[match(col1, temp)], count2 = total_count[match(col2, temp)], total_elements = n_distinct(ID) * 2, # 分组内总元素数=行数×2 Freqcol1 = count1 / total_elements, Freqcol2 = count2 / total_elements ) %>% # 整理目标列并去重 select(ID, col1, col2, recid, count1, count2, Freqcol1, Freqcol2) %>% distinct() %>% ungroup()
代码解释
- 分组生成全值列表:按
recid分组后,把每组的col1和col2合并成一个列表,再展开为长表,方便统计所有值的出现次数。 - 统计值出现次数:对展开后的
temp列计数,得到每个值在当前分组内的总出现次数。 - 关联原数据:通过
recid字段把统计结果和原表关联起来,保留原表的所有行。 - 计算count和频率:用
match函数匹配col1、col2对应的计数,再用分组内总元素数(行数×2)计算频率。 - 整理结果:筛选需要的列并去重,最后取消分组得到最终结果。
内容的提问来源于stack exchange,提问作者akang
相关产品推荐
相关产品推荐

