基于全国住院样本(National Inpatient Sample)数据集,使用R语言生成手术日期列的问题排查与解决方案请求
排查错误并实现手术日期列的解决方案
首先,咱们先拆解你遇到的问题和代码里的问题:
你的代码为什么会报错?
你看到的警告the condition has length > 1 and only the first element will be used,核心原因是你在if语句里用了整个列的向量比较(TBI$crani == "1"),而if只能处理长度为1的条件,R只会取第一个元素来判断,这显然不是你要的逐行处理逻辑。除此之外,你的代码还有几个关键问题:
- 循环范围错误:
for (i in 15)只会循环一次i=15,而不是遍历1到15的日期列 - 列引用错误:
TBI$PRDAYi无法识别变量i,R会把它当成一个叫PRDAYi的列,而不是动态生成PRDAY1、PRDAY2这类列名 - 逻辑混乱:第二个循环完全没有关联
TBI.crani的条件和PRDAY列的检查,函数返回值也没有正确对应每行的结果
正确的实现方案
根据你的需求:仅当TBI.crani=1且某列TBI.PRDAYn=1时,tts取对应的n;否则为NA。下面提供两种常用的实现方式:
方法1:Base R 实现
适合习惯原生R语法的场景:
# 先定位所有PRDAY开头的列(TBI.PRDAY1到TBI.PRDAY15) prday_cols <- grep("^TBI\\.PRDAY\\d+$", colnames(TBI)) # 定义处理单行的函数 get_surgery_day <- function(row) { # 如果未接受手术,直接返回NA if (row["TBI.crani"] != 1) { return(NA_integer_) } # 提取当前行的PRDAY列值,找到等于1的位置 prday_values <- row[prday_cols] target_pos <- which(prday_values == 1) # 处理多种情况:无匹配、多个匹配(这里取第一个匹配的日期) if (length(target_pos) == 0) { return(NA_integer_) } else { # 从列名中提取数字n return(as.integer(sub("TBI\\.PRDAY", "", names(prday_values)[target_pos[1]]))) } } # 对每一行应用函数,生成tts列 TBI$tts <- apply(TBI, 1, get_surgery_day)
方法2:Tidyverse 实现
如果你用的是tidyverse生态(你的数据是tbl_df格式,很适合这个方法):
library(tidyverse) TBI <- TBI %>% mutate( tts = case_when( # 未接受手术的行直接设为NA TBI.crani != 1 ~ NA_integer_, # 对接受手术的行,逐个检查PRDAY列 TRUE ~ pmap_int(select(., starts_with("TBI.PRDAY")), ~ { current_vals <- c(...) target_n <- which(current_vals == 1) # 无匹配返回NA,有匹配取第一个的n if (length(target_n) == 0) NA_integer_ else target_n[1] }) ) )
测试你的示例数据
你提供的前10行数据中TBI.crani全为0,所以运行后tts列会全部是NA,符合预期。如果后续有TBI.crani=1且TBI.PRDAYn=1的行,会自动提取对应的n值。
内容的提问来源于stack exchange,提问作者CodeRCodeP
相关产品推荐
相关产品推荐

