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

在R中按组补全日期与值,保留原始NA

按组补全日期并保留原始NA的后续空值需求

原始数据

原始数据框df如下:

group       date value
1     A 2022-12-01     1
2     A 2022-12-03     3
3     A 2022-12-06    NA
4     A 2022-12-08     1
5     B 2022-12-01     2
6     B 2022-12-05     2
7     C 2022-12-01     4
8     C 2022-12-06    NA
9     C 2022-12-08     6

dput代码:

df <- structure(list(group = c("A", "A", "A", "A", "B", "B", "C", "C", 
"C"), date = structure(c(1669849200, 1670022000, 1670281200, 
1670454000, 1669849200, 1670194800, 1669849200, 1670281200, 1670454000
), class = c("POSIXct", "POSIXt"), tzone = ""), value = c(1, 
3, NA, 1, 2, 2, 4, NA, 6)), class = "data.frame", row.names = c(NA, 
-9L))

预期输出

按组补全日期后,需保留原始NA,且该NA之后的补全行也保持NA,预期结果如下:

group       date value
 1 A     2022-12-01     1
 2 A     2022-12-02     1
 3 A     2022-12-03     3
 4 A     2022-12-04     3
 5 A     2022-12-05     3
 6 A     2022-12-06    NA
 7 A     2022-12-07    NA
 8 A     2022-12-08     1
 9 B     2022-12-01     2
10 B     2022-12-02     2
11 B     2022-12-03     2
12 B     2022-12-04     2
13 B     2022-12-05     2
14 C     2022-12-01     4
15 C     2022-12-02     4
16 C     2022-12-03     4
17 C     2022-12-04     4
18 C     2022-12-05     4
19 C     2022-12-06    NA
20 C     2022-12-07    NA
21 C     2022-12-08     6

需求关键点

  • 按group分组,补全每组内从最小日期到最大日期的所有单日日期
  • 补全日期对应的value需遵循:
    • 原始非NA值的前后补全行用前向填充
    • 原始NA需保留,且该NA之后的所有补全行(直到下一个原始非NA值)均保持NA

用户尝试的问题

  1. 仅使用complete补全日期,补全行的value均为NA,未实现填充:
library(dplyr)
library(tidyr)
df %>%
  group_by(group) %>%
  complete(., date = seq(min(date), max(date), by = 'day', fill = list(value = NA)))
  1. 添加fill函数后,原始NA被填充为前值,破坏原始数据:
df %>%
  group_by(group) %>%
  complete(., date = seq(min(date), max(date), by = 'day', fill = list(value = NA))) %>%
  fill(value, .direction = 'down')

解决方案

通过保存原始值、前向填充后恢复原始NA及后续空值的方式实现:

library(dplyr)
library(tidyr)

df %>%
  group_by(group) %>%
  # 补全每组内的所有单日日期
  complete(date = seq(min(date), max(date), by = "day")) %>%
  # 保存原始value,标记原始NA位置
  mutate(original_value = value) %>%
  # 前向填充所有空值
  fill(value, .direction = "down") %>%
  # 标记从第一个原始NA开始的所有行
  mutate(has_occured_na = cumany(is.na(original_value))) %>%
  # 恢复原始NA及之后补全行的空值
  mutate(value = ifelse(has_occured_na & is.na(original_value), NA, value)) %>%
  # 移除辅助列
  select(-original_value, -has_occured_na) %>%
  ungroup()

代码说明

  1. complete:按组补全日期区间内的所有单日日期
  2. mutate(original_value = value):保存原始value,避免填充后丢失原始NA的位置信息
  3. fill(value, .direction = "down"):前向填充所有空值,包括原始NA和补全产生的NA
  4. mutate(has_occured_na = cumany(is.na(original_value))):标记从第一个原始NA开始的所有行,确保后续行都被识别为需保留空值的区间
  5. mutate(value = ifelse(...)):对已出现原始NA的行,若为原始NA或补全产生的NA则恢复为空值,原始非NA值保留填充结果
  6. select:移除辅助列,得到最终结果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 05:25:21