如何为每个受试者计算后在DataFrame中插入新行并循环执行?
问题描述
有一个包含9名受试者的DataFrame,每名受试者有8组治疗前后的结果数据,结构如下:
| subID | treatment | outcome |
|---|---|---|
| 14325 | affected_pre_1 | 0.45 |
| 14325 | affected_pre_2 | 0.25 |
| 14325 | unaffected_pre_1 | 1.05 |
| 14325 | unaffected_pre_2 | 1.23 |
| 14325 | affected_post_1 | 0.22 |
| 14325 | affected_post_2 | 0.45 |
| 14325 | unaffected_post_1 | 0.87 |
| 14325 | unaffected_post_2 | 0.34 |
| 18964 | affected_pre_1 | 0.90 |
| 18964 | affected_pre_2 | 1.13 |
| 18964 | unaffected_pre_1 | 0.55 |
| 18964 | unaffected_pre_2 | 0.23 |
| 18964 | affected_post_1 | 0.17 |
| 18964 | affected_post_2 | 1.22 |
| 18964 | unaffected_post_1 | 1.89 |
| 18964 | unaffected_post_2 | 0.76 |
| 39274 | affected_pre_1 | 0.88 |
| 39274 | affected_pre_2 | 0.12 |
| 39274 | unaffected_pre_1 | 0.05 |
| 39274 | unaffected_pre_2 | 0.34 |
| 39274 | affected_post_1 | 0.99 |
| 39274 | affected_post_2 | 0.32 |
| 39274 | unaffected_post_1 | 1.81 |
| 39274 | unaffected_post_2 | 1.34 |
| ... | ... | ... |
需要为每名受试者生成4个新行,计算规则:
- row 1 = affected_pre_2 / affected_pre_1
- row 2 = unaffected_pre_2 / unaffected_pre_1
- row 3 = affected_post_2 / affected_post_1
- row 4 = unaffected_post_2 / unaffected_post_1
尝试过以下代码,但收到summarise()已弃用的警告:
data %>% bind_rows(data %>% summarise(subID = str_c(subID, lead(subID), sep = '_')) %>% na.omit() %>% bind_cols(data %>% summarise(across(5:11, ~ . - lead(.))) %>% na.omit()))
注:across(5:11 ...)指实际拥有的多个结果变量(示例仅保留一个简化展示)。不确定是否需要用apply函数,也不清楚如何按受试者循环执行流程。
解决方案
用tidyverse工具链即可完成,核心思路是拆分treatment列信息后按组计算比值,具体步骤如下:
1. 加载依赖包
library(tidyverse)
2. 单结果变量的处理代码
# 生成比值数据 ratio_data <- data %>% # 拆分treatment列,提取状态、时间、序号信息 separate(treatment, into = c("status", "time", "num"), sep = "_") %>% # 按受试者、状态、时间分组计算比值 group_by(subID, status, time) %>% summarise(outcome = outcome[num == "2"] / outcome[num == "1"], .groups = "drop") %>% # 生成新的treatment列名称 mutate(treatment = str_c(status, time, "ratio", sep = "_")) %>% # 调整列顺序与原数据一致 select(subID, treatment, outcome) # 若需将原数据与比值数据合并 combined_data <- bind_rows(data, ratio_data)
3. 多结果变量的适配处理
如果存在多个结果变量(对应原代码中的5:11列),只需修改summarise部分,用across批量处理:
ratio_data_multi <- data %>% separate(treatment, into = c("status", "time", "num"), sep = "_") %>% group_by(subID, status, time) %>% # 批量处理所有以outcome开头的列,也可改用5:11指定列位置 summarise(across(starts_with("outcome"), ~ .[num == "2"] / .[num == "1"]), .groups = "drop") %>% mutate(treatment = str_c(status, time, "ratio", sep = "_")) %>% select(subID, treatment, everything())
代码说明
separate()将treatment拆分为状态(affected/unaffected)、时间(pre/post)、序号(1/2)三列,便于精准分组。group_by(subID, status, time)确保每个受试者的每组状态-时间组合独立计算比值。summarise()直接提取序号2的结果除以序号1的结果,避免循环或apply类函数的复杂操作。
内容的提问来源于stack exchange,提问作者A.R.
相关产品推荐
相关产品推荐

