如何用dplyr为R数据框计算组均值及观测值均值偏差?
问题:自动生成R数据集中变量的组均值与偏差
数据集结构
myData <- structure(list(ID = c("a", "b", "c", "d", "e"), group = c("x", "y", "x", "x", "y"), var1 = c(0L, 0L, 2L, 0L, 0L), var2 = c(0, 0, 1, 0, 1), var3 = c(1.032, 0, 0, 0, 0)), row.names = c(NA, 5L), class = "data.frame")
查看数据集:
> myData ID group var1 var2 var3 1 a x 0 0 1.032 2 b y 0 0 0.000 3 c x 2 1 0.000 4 d x 0 0 0.000 5 e y 0 1 0.000
需求
为每个varN变量生成两个新变量:
varN_mean:对应group的均值varN_dev:个体观测值与组均值的偏差
最终期望输出格式:
> myData ID group var1_mean var1_dev var2_mean var2_dev var3_mean var3_dev 1 a x 0.667 -0.667 0.333 -0.333 0.344 0.688 2 b y 0 0 0.5 -0.5 0 0 3 c x 0.667 1.333 0.333 0.667 0.344 -0.344 4 d x 0.667 -0.667 0.333 -0.333 0.344 -0.344 5 e y 0 0 0.5 0.5 0 0
当前进展与问题
已用dplyr计算出组均值,但无法自动匹配列计算偏差:
library(dplyr) means_myData <- myData %>% group_by(group) %>% summarise( ID, across(starts_with("var"), .fns=~mean(.x), .names="{col}_mean") ) %>% ungroup()
尝试以下代码未成功:
means_myData %>% full_join(myData, by = c("ID", "group")) %>% summarise( ID, across(matches("^var._mean$"), .fns-~.x - ...) )
解决方案
推荐方法:分组后直接用mutate生成均值与偏差(高效适合大型数据集)
不需要先summarise再join,直接在group_by后使用mutate,一次性生成所有需要的列,避免额外的数据合并操作,性能更优:
library(dplyr) result <- myData %>% group_by(group) %>% mutate( # 生成组均值列 across(starts_with("var"), ~mean(.x, na.rm = TRUE), .names = "{col}_mean"), # 生成偏差列:原变量值减去对应组均值 across(starts_with("var"), ~.x - get(paste0(cur_column(), "_mean")), .names = "{col}_dev") ) %>% ungroup() %>% # 可选:调整列顺序,让均值、偏差与原变量对应排列 select(ID, group, starts_with("var"))
备选方法:基于已有的means_myData计算偏差
如果必须基于你已生成的means_myData,可以先合并原数据集,再通过列名匹配计算偏差:
library(dplyr) library(stringr) # 需要用到str_remove函数 result <- means_myData %>% full_join(myData, by = c("ID", "group")) %>% mutate( across(matches("^var.*_mean$"), ~ get(str_remove(cur_column(), "_mean")) - .x, .names = "{str_remove(col, '_mean')}_dev") ) %>% select(ID, group, starts_with("var")) # 可选调整列顺序
输出验证
运行上述代码后,查看结果(保留三位小数与示例一致):
> round(result, 3) # A tibble: 5 × 11 ID group var1 var2 var3 var1_mean var2_mean var3_mean var1_dev var2_dev var3_dev <chr> <chr> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 1 a x 0 0 1.03 0.667 0.333 0.344 -0.667 -0.333 0.688 2 b y 0 0 0 0 0.5 0 0 -0.5 0 3 c x 2 1 0 0.667 0.333 0.344 1.33 0.667 -0.344 4 d x 0 0 0 0.667 0.333 0.344 -0.667 -0.333 -0.344 5 e y 0 1 0 0 0.5 0 0 0.5 0
内容的提问来源于stack exchange,提问作者Giulio Centorame
相关产品推荐
相关产品推荐

