如何在R中提取数据框每行最后一个0前后的数值?
问题:提取R数据框中每行最后一个0前后的指定数值
现有如下R数据框:
df <- data.frame(id = c(1,2,3,4,5,6,7,8,9,10), X1 = c(1,1,0,2,8,0,1,3,4,5), X2 = c(0,2,3,NA,NA,6,NA,3,1,1), X3 = c(1,2,0,4,NA,6,7,5,NA,NA), X4 = c(4,NA,6,7,8,0,0,0,7,6), X5 = c(0,1,3,0,0,6,5,4,0,0), X6 = c(1,0,3,4,3,2,1,7,8,7), X7 = c(1,2,NA,4,5,7,8,NA,8,5), X8 = c(2,6,NA,6,5,NA,3,NA,NA,3))
查看数据:
> df id X1 X2 X3 X4 X5 X6 X7 X8 1 1 1 0 1 4 0 1 1 2 2 2 1 2 2 NA 1 0 2 6 3 3 0 3 0 6 3 3 NA NA 4 4 2 NA 4 7 0 4 4 6 5 5 8 NA NA 8 0 3 5 5 6 6 0 6 6 0 6 2 7 NA 7 7 1 NA 7 0 5 1 8 3 8 8 3 3 5 0 4 7 NA NA 9 9 4 1 NA 7 0 8 8 NA 10 10 5 1 NA 6 0 7 5 3
需求:为每个id提取每行中最后一个0之后的所有有效数值,以及最后一个0之前的最后一个数值,期望得到如下结果:
> df_new id a b1 b2 b3 b4 1 1 4 1 1 2 NA 2 2 1 2 6 NA NA 3 3 3 6 3 3 NA 4 4 7 4 4 6 NA 5 5 8 3 5 5 NA 6 6 6 6 2 7 NA 7 7 7 5 1 8 3 8 8 5 4 7 NA NA 9 9 7 8 8 NA NA 10 10 6 7 5 3 NA
解决方案
可以通过逐行处理的方式实现,这里使用dplyr结合purrr的函数完成,步骤如下:
- 加载所需包:
library(dplyr) library(purrr)
- 定义处理单行数据的函数:
process_row <- function(row) { # 提取除id外的数值列 vals <- row[-1] # 找到所有0的位置(忽略NA) zero_positions <- which(vals == 0 & !is.na(vals)) if (length(zero_positions) == 0) { # 容错处理:该行没有0的情况 a <- NA after_zero <- vals[!is.na(vals)] } else { # 定位最后一个0的位置 last_zero_pos <- max(zero_positions) # 提取最后一个0之前的最后一个有效数值 before_last_zero <- vals[1:(last_zero_pos - 1)] a <- tail(before_last_zero[!is.na(before_last_zero)], 1) # 提取最后一个0之后的所有有效数值 after_zero <- vals[(last_zero_pos + 1):length(vals)] after_zero <- after_zero[!is.na(after_zero)] } # 整理结果格式,补全到指定列数 result <- c(row[1], a, after_zero) names(result) <- c("id", "a", paste0("b", seq_along(after_zero))) # 统一补全到6列(id+a+4个b列),不足的位置填NA if (length(result) < 6) { result <- c(result, rep(NA, 6 - length(result))) names(result) <- c("id", "a", "b1", "b2", "b3", "b4") } as.data.frame(t(result)) }
- 对每行应用函数并合并结果:
df_new <- df %>% split(.$id) %>% map_dfr(process_row) %>% mutate(across(everything(), as.numeric))
运行后即可得到符合要求的df_new。
代码逻辑说明
- 先定位每行中所有0的位置,找到最后一个0的索引;
- 从开头到该索引的前一位,筛选非NA值并取最后一个,作为列
a; - 从该索引的后一位到行尾,筛选非NA值,作为
b1、b2等列; - 统一补全列数到
id+a+4个b列,不足的位置填充NA; - 最后合并所有行结果,转换为数值类型。
内容的提问来源于stack exchange,提问作者amisos55
相关产品推荐
相关产品推荐

