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

按data.frame分组对指定因子水平的val值求和的实现方法

分组筛选求和解决方案

需求说明

现有如下结构的data.frame:

fac1   fac2   fac3 val
1  Apple  Fresh    Red   2
2  Apple    Old    Red   3
3  Apple Hazard    Red   1
4 Banana  Fresh Yellow   4
5 Banana    Old Yellow   5
6 Banana Hazard Yellow   1
7  Berry  Fresh Purple   1
8  Berry    Old Purple   1
9  Berry Hazard Purple   3

需要按fac1的每个因子水平,筛选fac2等于**字符型值"Fresh"或"Old"**的行,对val列求和,同时保留fac3列,生成如下结构的结果:

fac1    fac3 sum.freshold
1  Apple    Red             5
2 Banana Yellow             9  
3  Berry Purple             2

示例数据代码

mydf <- data.frame(fac1 = c(rep("Apple", 3), rep("Banana", 3), rep("Berry", 3)), 
                   fac2 = rep(c("Fresh", "Old", "Hazard"), 3),
                   fac3 = c(rep("Red", 3), rep("Yellow", 3), rep("Purple", 3)), 
                   val = c(2,3,1,4,5,1,1,1,3), 
                   stringsAsFactors = T)

无效代码问题分析

你尝试的tapply代码无法得到目标结果,原因有两点:

  1. 函数内部使用了全局的mydf$fac2,但tapply传入的x是分组后的val子集,索引和原数据不匹配,导致筛选逻辑错误;
  2. tapply返回的是向量,无法直接生成包含fac1、fac3和求和列的data.frame。
# 无效代码
tapply(mydf$val, mydf$fac1, function(x) {x[mydf$fac2 == "Fresh"] + x[mydf$fac2 == "Old"]})

可行解决方案

方法1:使用dplyr包(语法直观)

library(dplyr)

result <- mydf %>%
  # 筛选fac2为Fresh或Old的行
  filter(fac2 %in% c("Fresh", "Old")) %>%
  # 按fac1和fac3分组(每个fac1对应唯一fac3,确保结果保留fac3)
  group_by(fac1, fac3) %>%
  # 求和并重命名列
  summarise(sum.freshold = sum(val), .groups = "drop")

方法2:使用Base R(无需额外包)

# 第一步:筛选符合条件的行
filtered_df <- mydf[mydf$fac2 %in% c("Fresh", "Old"), ]

# 第二步:按fac1和fac3分组求和
result <- aggregate(val ~ fac1 + fac3, data = filtered_df, FUN = sum)

# 第三步:重命名求和列
colnames(result)[3] <- "sum.freshold"

方法3:使用data.table包(大数据场景高效)

library(data.table)

# 转换为data.table格式
setDT(mydf)

# 筛选+分组求和
result <- mydf[fac2 %in% c("Fresh", "Old"), .(sum.freshold = sum(val)), by = .(fac1, fac3)]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 10:34:50