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

如何从R数据框指定列中提取最新非NA值生成新变量

R提取指定列最新非NA值生成新列的高效实现

现有如下R数据框df_test:

df_test<- data.frame(id = c("1a", "2a", "3a", "4a", "5a", "6a", "7a", "8a", "9a", "10a"),
                     baseline= c(-1,-1,-1,-1,-1,-1,-1,-1,-1,-1),
                     checkin1= c(0,NA,1, 2, NA, NA,NA, 1, NA, NA),
                     checkin2= c(-1,NA, NA,4,NA,NA,NA,NA,NA,NA),
                     checkin3= c(-1, 0, 1,1,1,2,2,NA,NA,2),
                     checkin4= c(NA,NA,NA,2,NA,NA,NA,NA,NA,1))

需要生成新列end,提取第3至6列(checkin1至checkin4,其中checkin4为最新记录、checkin1为最旧)中的最新非NA值;若该行无有效非NA值(如第9行),则新列值为NA,期望结果如下:

result<- data.frame(id = c("1a", "2a", "3a", "4a", "5a", "6a", "7a", "8a", "9a", "10a"),
                     baseline= c(-1,-1,-1,-1,-1,-1,-1,-1,-1,-1),
                     checkin1= c(0,NA,1, 2, NA, NA,NA, 1, NA, NA),
                     checkin2= c(-1,NA, NA,4,NA,NA,NA,NA,NA,NA),
                     checkin3= c(-1, 0, 1,1,1,2,2,NA,NA,2),
                     checkin4= c(NA,NA,NA,2,NA,NA,NA,NA,NA,1),
                     end= c(-1,0,1,2,1,2,2,1,NA,1))

已知可通过ifelse与mutate组合实现,但以下是更简洁直接的高效实现方式:


方法1:dplyr行处理 + last()

利用dplyr的行级处理能力,结合last()直接提取每行指定列的最后一个非NA值:

library(dplyr)

df_test %>%
  rowwise() %>%
  mutate(end = last(na.omit(c(checkin1, checkin2, checkin3, checkin4)), default = NA)) %>%
  ungroup()
  • 逻辑:na.omit()过滤当前行指定列的NA值,last()取过滤后的最后一个值(对应最新的checkin记录),default = NA确保无有效值时返回NA。

方法2:base R原生apply()实现

无需额外加载包,直接用base R的行应用函数完成:

df_test$end <- apply(df_test[, 3:6], 1, function(x) {
  valid_vals <- na.omit(x)
  if (length(valid_vals) == 0) NA else tail(valid_vals, 1)
})
  • 逻辑:apply()按行遍历第3-6列,na.omit()清理NA值,tail(valid_vals,1)取最后一个有效记录,无有效值时返回NA。

方法3:tidyr重塑数据提取

通过宽转长的方式筛选最新记录,再合并回原数据框:

library(dplyr)
library(tidyr)

df_test %>%
  pivot_longer(cols = checkin1:checkin4, names_to = "checkin", values_to = "value", values_drop_na = TRUE) %>%
  mutate(checkin_order = as.integer(sub("checkin", "", checkin))) %>%
  group_by(id) %>%
  filter(checkin_order == max(checkin_order)) %>%
  select(id, end = value) %>%
  right_join(df_test, by = "id") %>%
  select(names(df_test), end)
  • 逻辑:将checkin列转为长格式后提取每个checkin的序号,按id分组筛选序号最大的记录(最新),最后合并回原数据框补全缺失行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 13:12:53