R语言:按另一列分组统计数据框某列的出现次数
问题描述
我有一个包含字母列col1和颜色列col2的数据框:
x <- data.frame(col1=c("a","b","a","c","d","d","c","a","b","c"), col2=c("red","orange","yellow","red","red","yellow","orange","yellow","red","orange"))
对应的表格如下:
| col1 | col2 |
|---|---|
| a | red |
| b | orange |
| a | yellow |
| c | red |
| d | red |
| d | yellow |
| c | orange |
| a | yellow |
| b | red |
| c | orange |
我的目标是创建第二个数据框,统计x中每个col1字母对应的col2各颜色的出现次数,示例结果如下:
| Letters | Occurences | Red | Orange | Yellow |
|---|---|---|---|---|
| a | 3 | 1 | 0 | 2 |
| b | 2 | 1 | 1 | 0 |
| c | 3 | 1 | 2 | 0 |
| d | 2 | 1 | 0 | 1 |
目前由于col2仅有3个因子,我采用了手动逐个处理的暴力方法:
df <- data.frame(Letters = levels(factor(x$col1))) df$Occurences <- table(x$col1) df$red <- table(factor(x$col1[x$col2=="red"],levels=levels(factor(x$col1)))) df$orange <- table(factor(x$col1[x$col2=="orange"],levels=levels(factor(x$col1)))) df$yellow <- table(factor(x$col1[x$col2=="yellow"],levels=levels(factor(x$col1))))
请问是否有更简便的方法替代这种逐个列处理的方式?尤其是当数据集中col2的因子数量远多于3个时?
解决方案
方法一:基础R原生实现
利用table()生成交叉频数表,再结合rowSums()快速统计总次数,无需手动遍历每个颜色类别:
# 生成col1与col2的交叉频数表 cross_table <- table(x$col1, x$col2) # 转换为数据框并合并总出现次数 result_df <- data.frame( Letters = rownames(cross_table), Occurences = rowSums(cross_table), cross_table, row.names = NULL ) # 可选:调整颜色列名首字母大写以匹配示例格式 colnames(result_df)[3:ncol(result_df)] <- toupper(substring(colnames(result_df)[3:ncol(result_df)], 1, 1))
该方法会自动适配col2的所有类别,不管数量多少都无需修改代码。
方法二:tidyverse工具集实现
如果习惯使用tidyverse语法,可通过dplyr+tidyr的组合完成,代码可读性更强:
library(tidyverse) result_df <- x %>% # 按col1和col2分组统计频数 count(col1, col2) %>% # 将col2的类别转换为列,缺失值填充为0 pivot_wider(names_from = col2, values_from = n, values_fill = 0) %>% # 添加总出现次数列 mutate(Occurences = rowSums(select(., -col1))) %>% # 调整列顺序并重命名列名 relocate(Occurences, .after = col1) %>% rename(Letters = col1) %>% rename_with(~ str_to_title(.), cols = -c(Letters, Occurences))
此方法同样能自动识别col2的所有类别,适合处理大规模多类别数据。
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

