使用dplyr为指定列计算符合条件的行均值
基于dplyr筛选有效行计算分数均值
原始数据
df <- data.frame(name = c("Bill","Sally","John","Lucy","Jake","Rob","Sarah"), score1 = c(1,2,1,4,5,3,4), score2 = c(4,2,3,2,1,3,NA), score3 = c(3,4,1,4,NA,NA,NA), score4 = c(4,3,4,NA,NA,NA,NA), score5 = c(4,4,NA,NA,NA,NA,NA), score6 = c(1,NA,NA,NA,NA,NA,NA))
需求
仅针对score开头的列中非NA值数量≥4的行,计算分数均值并生成avg_score列;其余行的avg_score设为NA。
解决方案
方法1:行分组处理(逻辑直观)
通过行分组实现逐行判断与计算,适合理解行级操作逻辑:
library(dplyr) df <- df %>% rowwise() %>% mutate( # 统计每行score列的非NA值数量 non_na_count = sum(!is.na(c_across(starts_with("score")))), # 满足条件则计算均值(忽略NA),否则设为NA avg_score = ifelse(non_na_count >= 4, mean(c_across(starts_with("score")), na.rm = TRUE), NA) ) %>% select(-non_na_count) %>% # 移除中间计算用的计数列 ungroup() %>% mutate(avg_score = round(avg_score, 3)) # 保留三位小数匹配示例输出
方法2:向量化处理(高效版)
无需行分组,直接用向量级函数实现,处理大数据集时效率更高:
library(dplyr) df <- df %>% mutate( # 统计score列的非NA值数量 non_na_count = rowSums(!is.na(select(., starts_with("score")))), # 条件判断并计算均值 avg_score = ifelse(non_na_count >= 4, rowMeans(select(., starts_with("score")), na.rm = TRUE), NA) ) %>% select(-non_na_count) %>% mutate(avg_score = round(avg_score, 3))
最终输出
df # name score1 score2 score3 score4 score5 score6 avg_score # 1 Bill 1 4 3 4 4 1 2.833 # 2 Sally 2 2 4 3 4 NA 3.000 # 3 John 1 3 1 4 NA NA 2.250 # 4 Lucy 4 2 4 NA NA NA NA # 5 Jake 5 1 NA NA NA NA NA # 6 Rob 3 3 NA NA NA NA NA # 7 Sarah 4 NA NA NA NA NA NA
内容的提问来源于stack exchange,提问作者Bradley Allf
相关产品推荐
相关产品推荐

