多分组下基于T0均值的差值计算问题(R语言dplyr)
问题描述
现有如下结构的DataFrame:
structure(list(Batch = c("0L", "0L", "0L", "0L", "0L", "0L", "0L", "0L", "0L", "0L", "100L", "100L", "100L", "100L", "100L", "100L", "100L", "100L", "100L", "100L", "100L", "100L", "25L", "25L", "25L", "25L", "25L", "25L", "25L", "25L", "25L", "25L", "25L", "25L", "50L", "50L", "50L", "50L", "50L", "50L", "50L", "50L", "50L", "50L", "50L", "50L", "75L", "75L", "75L", "75L", "75L", "75L", "75L", "75L", "75L", "75L", "75L", "75L"), Time = c("T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0", "T0"), Treatment = c("U", "U", "T", "T", "T", "T", "T", "T", "T", "T", "U", "U", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "U", "U", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "U", "U", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "U", "U", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T"), Replicate = c(1, 2, 1, 2, 1, 2, 2, 1, 1, 2, 2, 3, 2, 3, 1, 2, 1, 2, 2, 3, 1, 3, 1, 2, 1, 3, 2, 3, 2, 3, 2, 3, 2, 3, 1, 2, 2, 3, 1, 2, 1, 2, 2, 3, 2, 3, 2, 3, 2, 3, 1, 3, 2, 3, 1, 2, 2, 3), Read_Count = c(1014, 3040, 29, 76, 8, 86, 20, 0, 1, 8, 5412, 6286, 8272, 12322, 751, 2667, 891, 2428, 2581, 4246, 575, 703, 516, 2469, 630, 945, 3135, 1888, 2086, 2289, 2802, 3736, 1120, 1756, 1001, 2087, 4858, 3248, 253, 715, 154, 775, 1333, 1242, 1211, 1579, 6168, 3952, 1916, 1636, 276, 337, 919, 1194, 109, 610, 605, 982), Organism = c("OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA", "OrgA"), Concentration = c(0, 0, 6.25, 6.25, 12.5, 12.5, 25, 49.75, 62.5, 62.5, 0, 0, 6.25, 6.25, 12.5, 12.5, 25, 25, 49.75, 49.75, 62.5, 62.5, 0, 0, 6.25, 6.25, 12.5, 12.5, 25, 25, 49.75, 49.75, 62.5, 62.5, 0, 0, 6.25, 6.25, 12.5, 12.5, 25, 25, 49.75, 49.75, 62.5, 62.5, 0, 0, 6.25, 6.25, 12.5, 12.5, 25, 25, 49.75, 49.75, 62.5, 62.5)), class = "data.frame", row.names = c(NA, 58L))
前20行数据示例:
Batch Time Treatment Replicate Read_Count Organism Concentration 1 0L T0 U 1 1014 OrgA 0.00 2 0L T0 U 2 3040 OrgA 0.00 3 0L T0 T 1 29 OrgA 6.25 4 0L T0 T 2 76 OrgA 6.25 5 0L T0 T 1 8 OrgA 12.50 6 0L T0 T 2 86 OrgA 12.50 7 0L T0 T 2 20 OrgA 25.00 8 0L T0 T 1 0 OrgA 49.75 9 0L T0 T 1 1 OrgA 62.50 10 0L T0 T 2 8 OrgA 62.50 11 100L T0 U 2 5412 OrgA 0.00 12 100L T0 U 3 6286 OrgA 0.00 13 100L T0 T 2 8272 OrgA 6.25 14 100L T0 T 3 12322 OrgA 6.25 15 100L T0 T 1 751 OrgA 12.50 16 100L T0 T 2 2667 OrgA 12.50 17 100L T0 T 1 891 OrgA 25.00 18 100L T0 T 2 2428 OrgA 25.00 19 100L T0 T 2 2581 OrgA 49.75 20 100L T0 T 3 4246 OrgA 49.75
需要按Batch、Organism、Time分组,对每个Concentration水平的T组,计算:
1 - [(Treatment为U的Read_Count均值 - Treatment为T的Read_Count均值) / Treatment为U的Read_Count均值]
以11-14行数据为例,计算结果应为1.760471876,对应公式:
1 - ((mean(c(5412, 6286)) - mean(c(8272, 12322))) / mean(c(5412, 6286)))
原尝试的dplyr代码无法得到正确结果:
bisDF <- bis %>% group_by(Batch, Time, Treatment, Organism, Concentration) %>% mutate(Via_Average = (1-(mean(Read_Count)-mean(Read_Count[Treatment == "T"])/mean(Read_Count))))
注:实际数据包含多个Organism,Time字段有T0之外的取值,所有TX值需与同组的T0值做差值计算。
解决方案
问题分析
原代码错误原因:
- 分组维度错误:把
Treatment和Concentration加入分组后,每个组内只有单一Treatment或浓度,无法跨Treatment计算均值 - 公式逻辑错误:缺少括号导致运算优先级错误,且分组内无法获取其他Treatment的均值
正确代码
基础版本(同Time内对比)
先提取U组的均值,再合并回原数据计算目标值:
library(dplyr) # 计算U组均值:按Batch、Organism、Time分组 u_means <- bis %>% filter(Treatment == "U") %>% group_by(Batch, Organism, Time) %>% summarise(u_mean = mean(Read_Count), .groups = "drop") # 合并均值并计算目标值 bisDF <- bis %>% left_join(u_means, by = c("Batch", "Organism", "Time")) %>% group_by(Batch, Organism, Time, Concentration, Treatment) %>% summarise( t_mean = mean(Read_Count), Via_Average = 1 - ((u_mean - t_mean) / u_mean), .groups = "drop" )
验证示例结果
针对Batch=100L、Organism=OrgA、Time=T0、Concentration=6.25的T组:
# 手动计算 u_mean_val <- mean(c(5412, 6286)) # 5849 t_mean_val <- mean(c(8272, 12322)) # 10297 1 - ((5849 - 10297)/5849) # 1.760472
与代码计算结果完全一致。
扩展版本(所有Time用T0的U组均值对比)
如果需要让非T0的Time值使用对应Batch/Organism的T0组U均值,调整如下:
# 提取T0的U组均值:按Batch、Organism分组 u_t0_means <- bis %>% filter(Treatment == "U", Time == "T0") %>% group_by(Batch, Organism) %>% summarise(u_t0_mean = mean(Read_Count), .groups = "drop") # 合并后计算所有Time的目标值 bisDF_extended <- bis %>% left_join(u_t0_means, by = c("Batch", "Organism")) %>% group_by(Batch, Organism, Time, Concentration, Treatment) %>% summarise( t_mean = mean(Read_Count), Via_Average = 1 - ((u_t0_mean - t_mean) / u_t0_mean), .groups = "drop" )
结果说明
最终结果会按Batch、Organism、Time、Concentration、Treatment汇总,每个组的Via_Average即为所需计算值。对于U组,t_mean等于u_mean,因此Via_Average会等于1,符合逻辑。
内容的提问来源于stack exchange,提问作者aminards
相关产品推荐
相关产品推荐

