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

如何在R中按行获取每位患者的最后有效观测值

在R中按行获取每行最后一个非NA观测值

以下是几种针对你的需求的实现方案,基于你提供的示例数据集:

首先重现你的数据集:

ID <- c(1:5)
Age <- c(23,34,26,18,35)
day1 <- c(NA,NA,NA,4,2)
day2 <- c(NA,3,NA,NA,NA)
day3 <- c(2,NA,3,NA,4)

mydata <- data.frame(ID, Age, day1, day2, day3)

方法1:基础R(apply函数)

适合小数据集,代码简洁直观:

# 提取所有以day开头的列,按行处理
mydata$last_value <- apply(mydata[, grep("^day", names(mydata))], 1, function(x) {
  non_na_vals <- x[!is.na(x)]
  # 处理整行全为NA的情况,返回NA
  if (length(non_na_vals) == 0) NA else tail(non_na_vals, 1)
})

运行后得到的结果:

ID Age day1 day2 day3 last_value
1  1  23   NA   NA    2          2
2  2  34   NA    3   NA          3
3  3  26   NA   NA    3          3
4  4  18    4   NA   NA          4
5  5  35    2   NA    4          4

方法2:dplyr(tidyverse风格)

适合习惯tidyverse语法的用户,可读性强:

library(dplyr)

mydata <- mydata %>%
  rowwise() %>%
  # 反转day列顺序后用coalesce取第一个非NA(对应原顺序的最后一个)
  mutate(last_value = coalesce(!!!rev(c_across(starts_with("day"))))) %>%
  ungroup()

如果需要处理全NA的行,可调整为:

mydata <- mydata %>%
  rowwise() %>%
  mutate(last_value = {
    vals <- c_across(starts_with("day"))[!is.na(c_across(starts_with("day")))]
    if (length(vals) == 0) NA else tail(vals, 1)
  }) %>%
  ungroup()

方法3:data.table(高效处理大数据)

当数据集规模较大时,data.table的性能优于apply和dplyr的rowwise模式:

library(data.table)

setDT(mydata)
# 指定day开头的列,按行计算
mydata[, last_value := apply(.SD, 1, function(x) {
  non_na_vals <- x[!is.na(x)]
  if (length(non_na_vals) == 0) NA else tail(non_na_vals, 1)
}), .SDcols = starts_with("day")]

更高效的无apply版本(避免逐行循环):

mydata[, last_value := {
  # 生成每行非NA值的位置矩阵
  na_mat <- !is.na(.SD)
  # 获取每行最后一个非NA值的列索引
  last_col_idx <- max.col(na_mat, ties.method = "last")
  # 根据索引提取对应值
  .SD[cbind(seq_len(.N), last_col_idx)]
}, .SDcols = starts_with("day")]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 04:50:24