在tidyverse中按组计算滚动均值的实现方案
解决分组滚动均值计算问题
核心思路
先按性别、教育水平分组计算原始均值,再针对每个性别组,基于数值窗口±1(即当前教育水平与其他水平差值≤1)的范围计算滚动均值,替换异常值并平滑结果。
完整实现代码
# 加载所需工具包 library(haven) library(tidyverse) library(zoo) # 读取数据(请替换为你的本地文件路径或数据来源) soep <- read_dta("your_data_path.dta") # 数据处理:计算原始均值 + 滚动均值 soep_processed <- soep %>% # 分组计算原始满意度均值与样本量 group_by(education, sex) %>% summarise( satisf_mean = mean(satisf_org, na.rm = TRUE), n = n() ) %>% ungroup() %>% # 按性别、教育水平排序,确保分组内数据有序 arrange(sex, education) %>% group_by(sex) %>% # 计算±1数值窗口的滚动均值 mutate( satisf_roll_mean = rollapplyr( data = tibble(edu = education, val = satisf_mean), width = n(), FUN = function(x) { current_edu = x$edu[which(x$edu == education)] # 筛选当前教育水平±1范围内的所有值,计算均值 mean(x$val[abs(x$edu - current_edu) <= 1], na.rm = TRUE) }, by.column = FALSE ) ) %>% ungroup() # 可视化对比原均值与滚动均值 soep_processed %>% ggplot(aes(x = education, col = as.factor(sex))) + geom_point(aes(y = satisf_mean), shape = 1, size = 3) + # 空心点为原均值 geom_point(aes(y = satisf_roll_mean), size = 3) + # 实心点为滚动均值 labs( title = "原满意度均值 vs ±1数值窗口滚动均值", x = "教育水平", y = "满意度均值", color = "性别", caption = "空心点=原始均值,实心点=滚动平滑后均值" )
关键细节说明
- 用
rollapplyr自定义窗口逻辑,严格基于数值差筛选,而非滞后/超前的位置邻居,适配你实际研究中年龄(连续数值)的场景 - 保留原始均值用于对比,清晰看到滚动平滑的效果
- 针对你提到的女性教育水平8.5的异常值,该逻辑会自动纳入7、8.5、9三个水平的均值计算,得到平滑后的结果
内容的提问来源于stack exchange,提问作者Marco
相关产品推荐
相关产品推荐

