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

如何在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的函数完成,步骤如下:

  1. 加载所需包:
library(dplyr)
library(purrr)
  1. 定义处理单行数据的函数:
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))
}
  1. 对每行应用函数并合并结果:
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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 21:55:36