You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 23:18:32