如何用group_by()实现按label分组的均值列归一化校正?
问题
现有如下示例数据框:
id_row sample wsts (xc)_mean wstm (xc)_mean label tube 1 Ta 2937.5 4082.5 well_1 S_PUC_C_064_(1)_G4 2 Ta 3048 5347.5 well_1 S_PUC_C_064_(1)_G4 3 Ca 6176 7735.5 well_2 S_PUC_C_064_(4)_G4 4 Ca 8431 13793 well_2 S_PUC_C_064_(4)_G4 7 blank 2723 2359 well_1 blank 8 blank 3456 8777 well_2 blank
需要完成以下操作:
- 识别所有含
_mean的列,按label分组计算:非blank样本的当前值减去同组blank样本的对应值 - blank样本直接保留原值
- 计算后生成以
_norm为后缀的新列(如wsts (xc)_mean→wsts (xc)_norm)
已有代码框架,需补充核心计算逻辑:
dataframe %>% group_by(label) %>% mutate(across(contains("_mean"), ..., .name = "{str_replace(.col, '_mean', '_norm')}"
预期结果示例:
id_row sample wsts (xc)_mean ... label tube wsts (xc)_norm 1 Ta 2937.5 ... well_1 S_PUC_C_064_(1)_G4 214.5 2 Ta 3048 ... well_1 S_PUC_C_064_(1)_G4 325 3 Ca 6176 ... well_2 S_PUC_C_064_(4)_G4 2720 4 Ca 8431 ... well_2 S_PUC_C_064_(4)_G4 4975 7 blank 2723 ... well_1 blank 2723 8 blank 3456 ... well_2 blank 3456
解决方案
直接在across中加入条件判断逻辑,结合分组内的空白值提取,完整代码如下:
library(dplyr) library(stringr) dataframe %>% group_by(label) %>% mutate(across(contains("_mean"), ~ if_else(sample == "blank", ., . - filter(cur_data(), sample == "blank") %>% pull(cur_column())), .name = "{str_replace(.col, '_mean', '_norm')}" )) %>% ungroup() # 可选,根据后续操作需求决定是否取消分组
逻辑说明
- 分组约束:按
label分组,确保空白校正仅在同组内执行 - 条件计算:
- 若当前行是blank样本,直接保留原值(
.代表当前列的原始值) - 若非blank样本,用当前值减去同组内blank样本的对应列数值:
filter(cur_data(), sample == "blank") %>% pull(cur_column())会精准提取当前分组、当前列的空白样本值
- 若当前行是blank样本,直接保留原值(
- 自动命名:通过
str_replace批量将原列名的_mean替换为_norm,生成标准化后的新列
结果验证
运行代码后会完全匹配预期:
- well_1组Ta样本:
2937.5 - 2723 = 214.5,3048 - 2723 = 325 - well_2组Ca样本:
6176 - 3456 = 2720,8431 - 3456 = 4975 - blank样本原值保持不变
内容的提问来源于stack exchange,提问作者Someone_1313
相关产品推荐
相关产品推荐

