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

如何用dplyr/tidyr按组仅填充非NA值上方的首个NA

按组仅填充非NA值上方第一个NA的实现方法

需求说明

对分组数据执行定向填充:仅将每个非NA值正上方紧邻的那个NA替换为该非NA值,其余NA保持不变,填充方向为"向上"(仅填充目标值的前一行)。tidyr::fill()无法直接实现该逻辑,因为它会填充所有上方连续的NA。

示例数据

df <- data.frame(g=c(1,1,1,1,1,1, 2,2,2,2,2,2,2),v=c(NA,NA,5,NA,8,NA, 1,1,NA,2,NA,NA,3))

原始数据:

g  v
1  1 NA
2  1 NA
3  1  5
4  1 NA
5  1  8
6  1 NA
7  2  1
8  2  1
9  2 NA
10 2  2
11 2 NA
12 2 NA
13 2  3

期望输出:

g  v
1  1 NA
2  1  5
3  1  5
4  1  8
5  1  8
6  1 NA
7  2  1
8  2  1
9  2  2
10 2  2
11 2 NA
12 2  3
13 2  3

解决方案(基于dplyr)

通过分组标记目标行,结合lead()函数实现精准填充:

library(dplyr)

result_df <- df %>%
  group_by(g) %>%
  mutate(
    # 标记需要填充的行:非NA值的上一行
    fill_target = row_number() %in% (which(!is.na(v)) - 1),
    # 对标记行,用下一行的非NA值填充
    v = ifelse(fill_target, lead(v), v)
  ) %>%
  select(-fill_target) %>%  # 移除辅助标记列
  ungroup()

print(result_df)

代码解释

  1. group_by(g):按分组变量g拆分数据,确保每个组内独立处理
  2. which(!is.na(v)):定位组内所有非NA值的行号,减1得到它们的上一行行号
  3. fill_target:生成布尔标记,标记出需要填充的行
  4. lead(v):获取当前行的下一行v值,对标记行替换原NA,非标记行保留原值
  5. select(-fill_target):清理辅助列,ungroup()取消分组

运行代码后即可得到符合要求的输出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 09:12:46