You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用sub函数更新DataFrame时R语言数学减法计算异常排查

解决缺失年龄计算的R脚本问题

问题背景

我有一个包含Age、Sex、MoB、YoB、MoI、YoI六列的患者数据DataFrame,其中后缀“B”代表生日(月/年),“I”代表疾病发病日期(月/年)。部分行Age值缺失,我想通过YoI与YoB的差值结合月份判断来计算这些行的Age,但编写的R脚本(使用dplyr)出现多个异常:

  • 使用age_calculated <- YoI - YoB时,2006-1940得到68而非正确的66;
  • 使用age_calculated <- YoI - YoB - 2能得到正确值,但不知道原因;
  • 使用目标公式age_calculated <- YoI + IafterB - YoB时,辅助列IafterB被忽略;
  • 测试age_calculated <- IafterB时,所有缺失Age的行都被设为0,证明IafterB未生效。

核心错误分析

  1. sub()函数误用:你用sub("-1", calculateAge(...), dataframe_csv$Age)替换缺失值,但sub()是字符串替换工具,它会把calculateAge()返回的向量转换成单个字符串,然后统一替换所有"-1",根本做不到逐行对应计算。这就是为什么测试IafterB时全变成0——sub只会用向量的第一个元素去替换所有匹配项。

  2. IafterB逻辑颠倒:你的case_when逻辑搞反了。正确逻辑是:

    • 如果发病月份晚于出生月份(MoI > MoB):当年生日已过,年龄=YoI-YoB;
    • 如果发病月份早于或等于出生月份(MoI ≤ MoB):生日还没过,年龄=YoI-YoB-1。
      你现在的判断条件刚好反过来,导致调整项完全错误。
  3. 数据类型混乱:读取CSV时,Age列因为混合了空值和数字被自动转成字符型,后续设为-1后还是字符型,计算时容易出现隐式转换错误。

修正后的完整脚本

# 初始化环境
library(dplyr)
message("\n开始修复缺失年龄数据\n")

# 定义文件路径(用file.path更稳妥,避免路径拼接错误)
base_path <- dirname(sys.frame(1)$ofile)
dataset_file_in <- file.path(base_path, "dataset_missing_age.csv")
dataset_file_out <- file.path(base_path, "dataset_fixed.csv")

# 打印路径信息
message(paste("基础路径                     :", base_path))
message(paste("输入数据集                   :", dataset_file_in))
message(paste("输出数据集                   :", dataset_file_out))

# 读取数据,指定字符串不转因子
dataframe_csv <- read.csv(dataset_file_in, sep=";", stringsAsFactors=FALSE)
message(paste("\n数据集行数                   :", nrow(dataframe_csv)))
message(paste("数据集列数                   :", length(dataframe_csv)))

# 修复缺失Age,全程用dplyr管道风格
dataframe_csv <- dataframe_csv %>%
  # 转换月份、年份为数值型,避免字符比较问题
  mutate(
    MoB = as.numeric(MoB),
    MoI = as.numeric(MoI),
    YoB = as.numeric(YoB),
    YoI = as.numeric(YoI)
  ) %>%
  # 计算年龄调整项:发病在生日后则不减,生日前则减1
  mutate(age_adjust = if_else(MoI > MoB, 0, -1)) %>%
  # 仅替换Age缺失的行,保留原有非缺失值
  mutate(
    Age = case_when(
      is.na(Age) ~ as.character(YoI - YoB + age_adjust),
      TRUE ~ Age
    )
  ) %>%
  # 移除临时辅助列
  select(-age_adjust)

# 打印修复后的结果
message("\n修复后的完整数据集:\n")
print(dataframe_csv)

# 保存结果到CSV
write.csv2(dataframe_csv, dataset_file_out, row.names = FALSE, quote=FALSE)
message("\n修复完成,结果已保存至指定路径")

测试验证

用你提供的测试数据,修复后缺失Age的行结果完全符合预期:

  • 第4行(MoB=3, YoB=1940; MoI=8, YoI=2006):2006-1940+0=66 ✔️
  • 第5行(MoB=4, YoB=1940; MoI=9, YoI=2006):2006-1940+0=66 ✔️
  • 第6行(MoB=6, YoB=1940; MoI=10, YoI=2006):2006-1940+0=66 ✔️
  • 第7行(MoB=8, YoB=1940; MoI=6, YoI=2006):2006-1940-1=65 ✔️
  • 第8行(MoB=10, YoB=1940; MoI=2, YoI=2006):2006-1940-1=65 ✔️
  • 第9行(MoB=11, YoB=1940; MoI=2, YoI=2006):2006-1940-1=65 ✔️
  • 第10行(MoB=12, YoB=1940; MoI=2, YoI=2006):2006-1940-1=65 ✔️

内容的提问来源于stack exchange,提问作者serkelion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 09:31:32