如何用group_by和mutate按分组执行T0减Tx的对数差值计算?
问题与解决方案
问题背景
数据框定义
mydf <- structure(list(Time = c("T0", "T3", "T3", "T0", "T3", "T3"), Organism = c("BB", "BB", "BB", "CR", "CR", "CR"), MOF = c("MOF", "MOF", "MOF", "MOF", "MOF", "MOF"), MOFTreatment = c("0", "0", "1", "0", "0", "1"), std_dev_groups = c(" 0.9228677", " 0.8464373", " 0.4491846", " 0.5988814", " 0.5845546", " 1.240182" ), Fold_reduction = c(" 1.8958800", " 1.7980552", " 1.3652684", " 1.5145418", " 1.4995760", " 2.362283"), Perc_viability = c("52.7459535", "55.6156459", "73.2456721", "66.0265686", "66.6855175", "42.331930" )), class = "data.frame", row.names = c(NA, -6L))
数据展示
Time Organism MOF MOFTreatment std_dev_groups Fold_reduction Perc_viability 1 T0 BB MOF 0 0.9228677 1.8958800 52.7459535 2 T3 BB MOF 0 0.8464373 1.7980552 55.6156459 3 T3 BB MOF 1 0.4491846 1.3652684 73.2456721 4 T0 CR MOF 0 0.5988814 1.5145418 66.0265686 5 T3 CR MOF 0 0.5845546 1.4995760 66.6855175 6 T3 CR MOF 1 1.240182 2.362283 42.331930
尝试代码及报错
尝试通过分组计算新增Log_loss列,但触发报错:
mydf2 <- mydf %>% group_by(Time, Organism, MOFTreatment) %>% mutate(Log_loss = (log10(100/Fold_reduction[Time == "T0"]) - log10(100/Fold_reduction[Time != "T0"])))
报错信息:
Error in `mutate()`: ℹ In argument: `Log_loss = (...)`. ℹ In group 1: `Time = "T0"`, `Organism = "BB"`, `MOFTreatment = "0"`. Caused by error in `100 / Fold_reduction[Time == "T0"]`: ! non-numeric argument to binary operator Backtrace: 1. mydf %>% group_by(Time, Organism, MOFTreatment) %>% ... 3. dplyr:::mutate.data.frame(...) 4. dplyr:::mutate_cols(.data, dplyr_quosures(...), by) 6. dplyr:::mutate_col(dots[[i]], data, mask, new_columns) 7. mask$eval_all_mutate(quo) 8. dplyr (local) eval()
需要执行的计算逻辑
针对每个Organism,用其Time=T0的Fold_reduction值,分别与该Organism下不同MOFTreatment的Time=T3值计算:
# BB的T0对应MOFTreatment=0的T3 log10(100/1.8958800) - log10(100/1.7980552) # BB的T0对应MOFTreatment=1的T3 log10(100/1.8958800) - log10(100/1.3652684) # CR的T0对应MOFTreatment=0的T3 log10(100/1.5145418) - log10(100/1.4995760) # CR的T0对应MOFTreatment=1的T3 log10(100/1.5145418) - log10(100/2.362283)
解决方案
错误原因分析
- 数据类型错误:
Fold_reduction等列是带空格的字符型,无法直接参与数值运算,导致non-numeric argument报错。 - 分组逻辑错误:按
Time, Organism, MOFTreatment分组后,每个组仅包含单行数据,无法跨Time取数计算。
正确代码
library(dplyr) # 1. 清洗数据:将带空格的字符型数值转为数值型 mydf_clean <- mydf %>% mutate(across(c(std_dev_groups, Fold_reduction, Perc_viability), ~ as.numeric(trimws(.)))) # 2. 计算Log_loss列 mydf_final <- mydf_clean %>% # 按Organism分组,提取每个生物的T0对应的Fold_reduction值 group_by(Organism) %>% mutate(T0_Fold = Fold_reduction[Time == "T0"]) %>% ungroup() %>% # 仅对T3行计算Log_loss,T0行设为NA mutate(Log_loss = ifelse(Time == "T3", log10(100/T0_Fold) - log10(100/Fold_reduction), NA))
代码说明
- 数据清洗:用
trimws()去掉数值字符串的空格,再转成数值型,解决运算类型错误。 - 提取基准值:按
Organism分组后,提取每个生物Time=T0的Fold_reduction作为基准值T0_Fold。 - 条件计算:仅对
Time=T3的行执行目标计算,T0行设为NA,符合需求逻辑。
最终结果示例
> mydf_final # A tibble: 6 × 8 Time Organism MOF MOFTreatment std_dev_groups Fold_reduction Perc_viability Log_loss <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> 1 T0 BB MOF 0 0.923 1.90 52.7 NA 2 T3 BB MOF 0 0.846 1.80 55.6 0.0217 3 T3 BB MOF 1 0.449 1.37 73.2 0.137 4 T0 CR MOF 0 0.599 1.51 66.0 NA 5 T3 CR MOF 0 0.585 1.50 66.7 0.00390 6 T3 CR MOF 1 1.24 2.36 42.3 -0.190
内容的提问来源于stack exchange,提问作者aminards
相关产品推荐
相关产品推荐

