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

如何从数据框每行反向提取首个非NA的收入值?

解决方法:从每行反向选取首个非NA值生成新列

针对你的需求,这里提供几种常用的R语言实现方式:

方法一:R基包原生操作

无需额外安装包,直接用基包函数实现:

# 定义原始数据框
wave <- data.frame(ID=c(1, 2, 3, 4, 5, 6),
                   income_wave_1_2017=c(109, 106, NA, 10, 65, NA),
                   income_wave_2_2018=c(NA, 108, 66, NA, NA, 190),
                   income_wave_3_2019=c(19, NA, NA, NA, NA, NA))

# 提取所有收入相关列
income_cols <- wave[, grep("^income_wave", colnames(wave))]

# 逐行反转列顺序,取第一个非NA值生成新列
wave$newest_income_ <- apply(income_cols, 1, function(x) {
  rev_x <- rev(x)
  rev_x[!is.na(rev_x)][1]
})

# 保留需要的列
wave <- wave[, c("ID", "newest_income_")]

方法二:tidyverse工具包(简洁高效)

推荐使用dplyr+tidyr组合,代码可读性更强:

library(tidyverse)

# 定义原始数据框
wave <- data.frame(ID=c(1, 2, 3, 4, 5, 6),
                   income_wave_1_2017=c(109, 106, NA, 10, 65, NA),
                   income_wave_2_2018=c(NA, 108, 66, NA, NA, 190),
                   income_wave_3_2019=c(19, NA, NA, NA, NA, NA))

wave <- wave %>%
  rowwise() %>%
  # 提取所有收入列,去掉NA后取最后一个值(即最晚的非NA数据)
  mutate(newest_income_ = last(na.omit(c_across(starts_with("income_wave"))))) %>%
  ungroup() %>%
  select(ID, newest_income_)

注:这里利用收入列按年份从早到晚排列的特性,na.omit后取last等价于从后往前找首个非NA值。

方法三:data.table包(大数据量首选)

如果你的数据量较大,data.table的运行效率会显著高于基包和tidyverse:

library(data.table)

# 定义原始数据框并转为data.table格式
wave <- data.frame(ID=c(1, 2, 3, 4, 5, 6),
                   income_wave_1_2017=c(109, 106, NA, 10, 65, NA),
                   income_wave_2_2018=c(NA, 108, 66, NA, NA, 190),
                   income_wave_3_2019=c(19, NA, NA, NA, NA, NA))
setDT(wave)

# 指定收入列,逐行处理生成新列
income_cols <- grep("^income_wave", colnames(wave), value = TRUE)
wave[, newest_income_ := apply(.SD, 1, function(x) rev(x)[!is.na(rev(x))][1]), .SDcols = income_cols]

# 保留需要的列
wave <- wave[, .(ID, newest_income_)]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 10:20:25