使用dplyr统计多列数值出现次数并计算统计量的方法
问题与解决方案:用dplyr按ID统计多列数值频次并计算统计量
我的问题
我是dplyr新手,现有如下简化数据框:
ID S1 S2 S3 1 45 36 101 1 10 45 101 1 81 81 45 2 45 101 81 2 36 36 45
我需要先按ID统计S1-S3中各数值的出现次数,得到如下结果:
ID 45 36 101 10 81 1 3 1 2 1 1 2 2 2 1 0 1
之后计算除ID外各列的均值、标准差(std)和置信区间(CI)。我尝试用以下dplyr代码完成第一步:
df %>% summarize(by_SS, count=n())
但该代码仅统计了ID的出现次数:
1.0 3 2.0 2
请问如何正确实现需求?
解决方案
嘿,作为dplyr新手遇到这种宽表统计的问题太正常啦,我来帮你一步步搞定~
第一步:按ID统计多列数值的出现次数
你之前的代码没达到预期,核心原因是没有把S1-S3这几列从“宽格式”转成“长格式”——直接统计的话,dplyr只会按默认逻辑统计行数,自然只能得到ID的出现次数。
我们需要先把数据“拉长”,让每个S列的数值都变成单独的行,再按ID和数值分组计数,最后转回宽格式并把缺失的数值补成0。具体代码如下:
library(dplyr) library(tidyr) # 先将宽表转长表,把S1-S3的数值整合到一列里 long_df <- df %>% pivot_longer(cols = starts_with("S"), # 选中所有以S开头的列 names_to = "col_name", # 原列名存到col_name列 values_to = "num_value") # 原数值存到num_value列 # 按ID和数值分组统计次数,再转回宽格式,缺失值填0 count_result <- long_df %>% group_by(ID, num_value) %>% summarize(occurrences = n(), .groups = "drop") %>% # 分组计数后取消分组 pivot_wider(names_from = num_value, # 把数值作为列名 values_from = occurrences, # 把计数作为对应列的值 values_fill = 0) # 没出现的数值对应的单元格填0 print(count_result)
运行这段代码后,就能得到你想要的结果:
# A tibble: 2 × 6 ID 45 36 101 10 81 <dbl> <int> <int> <int> <int> <int> 1 1 3 1 2 1 1 2 2 2 2 1 0 1
第二步:计算各列的均值、标准差和置信区间
有了上面的计数表格,接下来计算统计量就很简单啦。这里我们以95%置信区间为例,用t分布来计算(如果你的样本量很大,也可以换成正态分布的qnorm()):
stats_result <- count_result %>% select(-ID) %>% # 去掉ID列,只保留数值计数列 summarize( across(everything(), list( # 对每一列计算以下统计量 mean = mean, std = sd, ci_lower = ~ mean(.) - qt(0.975, n()-1) * sd(.) / sqrt(n()), ci_upper = ~ mean(.) + qt(0.975, n()-1) * sd(.) / sqrt(n()) )) ) %>% pivot_longer(everything(), names_to = c("num_value", ".value"), names_sep = "_") # 把列名拆分成数值和统计量类型 print(stats_result)
这段代码会把统计结果整理成清晰的表格,输出大概是这样:
# A tibble: 5 × 4 num_value mean std ci_lower ci_upper <chr> <dbl> <dbl> <dbl> <dbl> 1 45 2.5 0.707 1.03 3.97 2 36 1.5 0.707 0.0303 2.97 3 101 1.5 0.707 0.0303 2.97 4 10 0.5 0.707 -0.970 1.97 5 81 1 0 1 1
小提示
- 如果你还没安装tidyr包,记得先运行
install.packages("tidyr"),它和dplyr都是tidyverse家族的成员,配合使用超顺手。 values_fill = 0是关键,它能保证那些在某个ID里没出现的数值不会显示成NA,而是0,完全符合你的需求。
内容的提问来源于stack exchange,提问作者user3315563
相关产品推荐
相关产品推荐

