如何在R中生成新列,实现行内非NA值左移并填充至新列开头
解决方案
Base R 方法
可以使用apply()逐行处理数据,自定义函数实现从第一个非NA值开始截取后续元素(包含中间的NA),并将长度补至5个(不足的位置填充NA):
# 定义处理单行的函数 process_row <- function(row) { # 找到第一个非NA值的位置 first_non_na <- which(!is.na(row))[1] # 若整行都是NA,返回全NA的向量 if (is.na(first_non_na)) { return(rep(NA, 5)) } # 从第一个非NA值开始截取后续元素,补NA至5个长度 row_subset <- row[first_non_na:length(row)] c(row_subset, rep(NA, 5 - length(row_subset))) } # 应用函数到每行,生成T1-T5列 df[, paste0("T", 1:5)] <- t(apply(df, 1, process_row)) # 查看结果 df
运行后得到的结果与期望完全一致:
X1 X2 X3 X4 X5 T1 T2 T3 T4 T5 1 NA NA NA 1 2 1 2 NA NA NA 2 NA 0 2 1 NA 0 2 1 NA NA 3 7 0 3 5 NA 7 0 3 5 NA 4 8 NA 4 2 4 8 NA 4 2 4 5 1 3 2 1 3 1 3 2 1 3 6 5 7 7 7 NA 5 7 7 7 NA
Tidyverse 方法
如果习惯使用tidyverse工具链,可以结合dplyr和purrr实现:
library(dplyr) library(purrr) df <- df %>% mutate( # 逐行处理,生成T列的列表 t_cols = pmap(across(X1:X5), ~{ row <- c(...) first_non_na <- which(!is.na(row))[1] if (is.na(first_non_na)) { rep(NA, 5) } else { row_subset <- row[first_non_na:length(row)] c(row_subset, rep(NA, 5 - length(row_subset))) } }) ) %>% # 将列表列拆分为T1-T5列 unnest_wider(t_cols, names_sep = "") %>% rename_with(~paste0("T", 1:5), starts_with("t_cols"))
这段代码同样能生成符合要求的结果,适合熟悉tidyverse语法的用户。
内容的提问来源于stack exchange,提问作者user21027866
相关产品推荐
相关产品推荐

