R语言按分组统计列中满足条件的观测值占比问题求助
没问题,我来帮你搞定这个统计需求!
首先先修正你提供的数据集读取代码(原始文本格式存在小问题,调整后才能正确加载数据):
mydata <- read.table(header=TRUE, text=" rime point sound school 50 80 50 es 80 80 20 es 5 90 80 es 0 10 80 ms 50 80 50 ms 80 80 20 ms 5 90 80 hs 0 10 80 hs 5 90 80 hs 0 10 80 hs ")
你之前用summarise_at搭配sum只能得到数值总和,而我们需要的是每组中列值≥50的观测占比。核心逻辑是计算满足条件的行数占组内总行数的比例,再转成百分比格式。这里推荐用dplyr的across函数(summarise_at已处于软弃用状态,across是更现代的写法),具体解决方案如下:
方法一:借助scales包快速生成标准百分比
library(dplyr) library(scales) # 用于便捷生成百分比格式 mydata_clean <- mydata %>% group_by(school) %>% # 对指定列计算≥50的占比,并转成带一位小数的百分比 summarise(across(c(rime, point, sound), ~ percent(mean(.x >= 50), accuracy = 0.1))) %>% # 把school列移到最后,和你的预期结果格式一致 relocate(school, .after = last_col())
方法二:不依赖额外包,手动格式化百分比
如果你不想安装scales包,可以用sprintf手动生成百分比字符串:
library(dplyr) mydata_clean <- mydata %>% group_by(school) %>% summarise(across(c(rime, point, sound), ~ sprintf("%.1f%%", mean(.x >= 50) * 100))) %>% relocate(school, .after = last_col())
关键代码解释
group_by(school):按school分组,确保后续统计是基于每组内部的观测数据mean(.x >= 50):这是核心逻辑——逻辑值TRUE会被当作1,FALSE当作0,所以均值就是满足≥50的观测占组内总行数的比例percent(...)/sprintf(...):把比例数值转成你需要的百分比格式(比如66.7%)relocate(...):调整列的顺序,让school列放在最后,和你给出的预期结果完全匹配
运行代码后,你会得到和预期一致的结果:
# A tibble: 3 × 4 rime point sound school <chr> <chr> <chr> <chr> 1 66.7% 100% 66.7% es 2 66.7% 66.7% 66.7% ms 3 0% 50% 100% hs
内容的提问来源于stack exchange,提问作者Mishalb
相关产品推荐
相关产品推荐

