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

基于多列条件计算数据框列值的均值与标准差(R语言)

解决方案:可扩展的条件统计计算

针对你的需求,我提供一个基于tidyverse的可扩展方案,它能轻松适配新增的条件列或价格列,同时处理"-"表示忽略条件的逻辑。

步骤1:加载依赖包并定义关键变量

首先我们加载tidyverse工具集,然后明确哪些列是条件列(用于筛选),哪些是价格列(用于计算均值和标准差)——这两个变量是实现扩展性的核心,后续新增列只需修改这里即可。

library(tidyverse)

# 定义条件列和价格列,可根据需求扩展
condition_cols <- c("Colour", "Type", "Size")
price_cols <- c("PriceOne", "PriceTwo")

步骤2:编写可复用的统计计算函数

我们写一个函数,输入一行条件(来自my.df2),输出对应的价格列统计值。函数会自动跳过值为"-"的条件列,处理无匹配结果的情况(返回NA)。

calculate_stats <- function(...) {
  # 获取当前行的条件参数
  current_conditions <- tibble(...) %>% select(all_of(condition_cols))
  
  # 逐步筛选my.df1:仅保留符合非"-"条件的行
  filtered_df <- my.df1
  for (col in condition_cols) {
    val <- current_conditions[[col]]
    if (val != "-") {
      filtered_df <- filtered_df %>% filter(.data[[col]] == val)
    }
  }
  
  # 处理无匹配结果的情况,否则计算均值和标准差
  if (nrow(filtered_df) == 0) {
    stats <- set_names(rep(NA_real_, 2 * length(price_cols)), 
                       c(paste0(price_cols, "Mean"), paste0(price_cols, "StDev")))
  } else {
    stats <- filtered_df %>%
      summarise(across(all_of(price_cols), 
                      list(Mean = mean, StDev = sd), 
                      .names = "{.col}{.fn}")) %>%
      unlist()
  }
  
  return(stats)
}

步骤3:应用函数到my.df2的每一行

用pmap_dfr遍历my.df2的每一行条件,计算统计值并合并回原数据框:

my.df2_result <- my.df2 %>%
  mutate(pmap_dfr(select(., all_of(condition_cols)), calculate_stats))

验证结果(以第5行为例)

my.df2第5行的条件是Colour=Blue、Type=2、Size="-",即筛选my.df1中所有Colour=Blue且Type=2的行:

  • PriceOne均值:(20+18+11+20+21+11)/6 ≈ 16.8333
  • PriceOne标准差:≈4.717
  • PriceTwo均值:(10+18+14+28+19+11)/6 ≈16.6667
  • PriceTwo标准差:≈6.922

查看my.df2_result的第5行,会得到完全匹配的结果。

大数据集优化:data.table版本

如果你的数据集非常大,推荐使用data.table实现,效率更高:

library(data.table)

setDT(my.df1)
setDT(my.df2)

calculate_stats_dt <- function(row) {
  # 构建筛选表达式
  i_expr <- Reduce(function(x, y) {
    val <- row[[y]]
    if (val == "-") x else paste(x, y, "==", shQuote(val), sep = " & ")
  }, condition_cols, init = "")
  i_expr <- sub("^ & ", "", i_expr)
  
  # 筛选数据
  filtered <- if (i_expr == "") my.df1 else my.df1[eval(parse(text = i_expr))]
  
  # 计算统计值
  if (nrow(filtered) == 0) {
    stats <- as.list(set_names(rep(NA_real_, 2*length(price_cols)), 
                               c(paste0(price_cols, "Mean"), paste0(price_cols, "StDev"))))
  } else {
    stats <- filtered[, lapply(.SD, function(x) list(Mean = mean(x), StDev = sd(x))), .SDcols = price_cols]
    stats <- unlist(stats, recursive = FALSE)
    names(stats) <- paste0(rep(price_cols, each=2), c("Mean", "StDev"))
  }
  
  return(stats)
}

# 应用到每一行
my.df2_result_dt <- my.df2[, c(.SD, calculate_stats_dt(.SD)), by = seq_len(nrow(my.df2))]
my.df2_result_dt[, seq_len := NULL]

扩展性说明

  • 新增条件列:比如加Brand列,只需把"Brand"添加到condition_cols向量
  • 新增价格列:比如加PriceThree列,只需把"PriceThree"添加到price_cols向量
  • 函数会自动处理所有新增列,无需修改核心逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:26:34