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

如何用dplyr/tidyr/purrr按行对数据框应用Hmisc::wtd.mean

使用dplyr/tidyr/purrr实现行级加权均值计算

我来帮你把现有的循环逻辑转换成tidyverse风格的实现,这里提供几种不同的思路,都能得到和你循环代码完全一致的结果,而且代码更简洁易维护:

方法1:用dplyr的rowwise() + c_across()(最直观)

这种方法最贴近你原来的循环逻辑,通过rowwise()告诉dplyr按行处理数据,c_across()可以快速选中指定列:

library(dplyr)
library(Hmisc)

# 基于你的原始数据框df进行计算
df <- df %>%
  rowwise() %>%
  mutate(
    weighted.means = wtd.mean(
      x = c_across(starts_with("mean")),  # 选中所有以mean开头的列
      weights = c_across(starts_with("weight"))  # 选中所有以weight开头的列
    )
  ) %>%
  ungroup()  # 取消按行分组,恢复常规数据框状态

# 验证结果和原循环一致
all.equal(df$weighted.means, c(70.74705, 82.85015, 82.40826, 73.35798, 70.02986, 74.05543, 73.64709, 77.12899, 72.56236, 84.74055))
# 输出TRUE

方法2:用purrr的pmap()(灵活的行级函数映射)

如果需要更灵活的行级操作,可以用pmap()来逐行传递参数给wtd.mean:

library(purrr)
library(dplyr)
library(stringr)
library(Hmisc)

df <- df %>%
  mutate(
    weighted.means = pmap_dbl(., function(...) {
      # 把当前行的所有列转换成列表
      row_data <- list(...)
      # 提取mean和weight列的值
      mean_vals <- unlist(row_data[str_detect(names(row_data), "^mean")])
      weight_vals <- unlist(row_data[str_detect(names(row_data), "^weight")])
      # 计算加权均值
      wtd.mean(x = mean_vals, weights = weight_vals)
    })
  )

或者更简洁的版本,先把mean和weight列打包成列表列,再用map2_dbl()映射:

df <- df %>%
  mutate(
    mean_list = pmap(list(.), ~ c_across(starts_with("mean"))),
    weight_list = pmap(list(.), ~ c_across(starts_with("weight"))),
    weighted.means = map2_dbl(mean_list, weight_list, ~ wtd.mean(.x, .y))
  ) %>%
  select(-mean_list, -weight_list)  # 移除中间生成的列表列

方法3:用tidyr重塑数据(适合多步骤行级分析)

如果后续还要对每行的mean和weight做更多处理,可以先把数据转成长格式,分组计算后再转回宽格式:

library(tidyr)
library(dplyr)
library(Hmisc)

df <- df %>%
  mutate(row_id = row_number()) %>%  # 添加行ID用于分组
  pivot_longer(
    cols = -row_id,
    names_to = c(".value", "num"),  # 拆分列名,.value表示保留的列类型(weight/mean)
    names_pattern = "(weight|mean)(\\d+)"  # 正则匹配列名的前缀和数字
  ) %>%
  group_by(row_id) %>%
  summarize(weighted.means = wtd.mean(mean, weights = weight)) %>%
  right_join(df, by = "row_id") %>%  # 和原始数据合并
  select(-row_id)  # 移除行ID列

方法对比

  • 方法1最直观,代码量最少,适合快速实现;
  • 方法2灵活性最高,适合需要对每行数据做复杂预处理的场景;
  • 方法3适合需要对每行的mean/weight对做额外分析(比如检查权重和是否为1)的场景。

内容的提问来源于stack exchange,提问作者Eric

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:30:26