在R语言中基于条件用指定行值替换特定行值的tidyverse解法
用tidyverse处理RCT宽格式数据的替换与清理
先模拟一份和你场景匹配的宽格式数据,方便演示操作:
library(tidyverse) set.seed(123) df <- tibble( ID = c("ID1", "ID1", "ID1", "ID2", "ID3", "ID3", "ID4"), TIME = c("t1", "t1.5", "t2", "t1", "t1", "t1.5", "t2"), OUTCOME = c(45, 48, 52, 60, 40, 44, 55), OTHER_VAR = rnorm(7) # 保留其他协变量 ) # 你已有的需要替换的ID向量 pesky_IDs <- c("ID1", "ID3")
直接用tidyverse的链式操作一步到位:
cleaned_df <- df %>% # 按ID分组,只处理同一参与者的时间点 group_by(ID) %>% # 提取t1.5的OUTCOME值,填充到同ID的所有行 mutate( t1.5_val = if_else(TIME == "t1.5", OUTCOME, NA_real_), t1.5_val = fill(t1.5_val, .direction = "updown") ) %>% ungroup() %>% # 给目标ID的t1行替换OUTCOME值 mutate( OUTCOME = case_when( ID %in% pesky_IDs & TIME == "t1" ~ t1.5_val, TRUE ~ OUTCOME ) ) %>% # 清理临时列和t1.5行 select(-t1.5_val) %>% filter(TIME != "t1.5")
代码逻辑说明
group_by(ID):把同一参与者的所有行归为一组,避免跨ID混淆数据fill(t1.5_val, .direction = "updown"):把t1.5行的OUTCOME值复制到同ID的t1、t2行,这样t1行就能直接拿到要替换的值case_when():精准控制替换范围——只给pesky_IDs里的ID的t1行替换值,其他行保持原样- 最后两步删掉临时辅助列和不需要的t1.5行,得到干净的数据集
多结局变量的扩展方案
如果你的数据有多个结局变量(比如OUTCOME1、OUTCOME2),可以用across()批量处理:
cleaned_df_multi <- df %>% group_by(ID) %>% # 批量提取所有结局变量的t1.5值 mutate( across(starts_with("OUTCOME"), ~ if_else(TIME == "t1.5", ., NA_real_), .names = "{.col}_t1.5"), across(ends_with("_t1.5"), fill, .direction = "updown") ) %>% ungroup() %>% # 批量替换目标行的结局值 mutate( across(starts_with("OUTCOME"), ~ case_when( ID %in% pesky_IDs & TIME == "t1" ~ get(str_c(cur_column(), "_t1.5")), TRUE ~ . )) ) %>% select(-ends_with("_t1.5")) %>% filter(TIME != "t1.5")
内容的提问来源于stack exchange,提问作者TeeCee
相关产品推荐
相关产品推荐

