用前后值的平均值填充 NA 值

fill NA values with mean of preceding and subsequent values

我正在处理一个包含一些缺失值的天气变量(温度、降水等)数据集。由于我的具体方法(几天内对这些变量求和),我需要处理数据集中的 NA 值。

当缺少每日值时,我想用前一天和第二天的平均值来填充那一天。这里的假设是天气值从一天到下一天都是相似的。是的,我意识到这是一个很大的假设。

我开发了以下内容:

maxTemp <- c(13.2, 10.7, NA, 17.9, 6.6, 10, 13, NA, NA, 8.8, 9.9, 14.9, 16.3, NA, 18, 9.9, 11.5, 15.3, 21.7, 23.9, 26.6, 27, 22.3, NA, 17.9)
weather <- as.data.frame(maxTemp)
weather %>% 
  mutate(maxTempNA = if_else(is.na(maxTemp),
                             (lag(maxTemp) + lead(maxTemp))/2,
                             maxTemp))

但是,在少数情况下,我连续几天有两个 NA 值,所以这不起作用。关于编码方法的任何想法,以便当连续有两个(或更多)NA 时,平均值使用 'bookending' 值来填充 NA?

最终结果应该是这样的:

maxTemp <- c(13.2, 10.7, 14.3, 17.9, 6.6, 10, 13, 10.9, 10.9, 8.8, 9.9, 14.9, 16.3, 17.15, 18, 9.9, 11.5, 15.3, 21.7, 23.9, 26.6, 27, 22.3, 20.1, 17.9)

如何使用 approxNAs 替换为插值;默认情况下,approx 使用线性插值,因此这应该与您的手动替换均值结果匹配。

weather %>%
    mutate(maxTemp_interp = approx(1:n(), maxTemp, 1:n())$y)
#    maxTemp maxTemp_interp
# 1     13.2          13.20
# 2     10.7          10.70
# 3       NA          14.30
# 4     17.9          17.90
# 5      6.6           6.60
# 6     10.0          10.00
# 7     13.0          13.00
# 8       NA          11.60
# 9       NA          10.20
# 10     8.8           8.80
# 11     9.9           9.90
# 12    14.9          14.90
# 13    16.3          16.30
# 14      NA          17.15
# 15    18.0          18.00
# 16     9.9           9.90
# 17    11.5          11.50
# 18    15.3          15.30
# 19    21.7          21.70
# 20    23.9          23.90
# 21    26.6          26.60
# 22    27.0          27.00
# 23    22.3          22.30
# 24      NA          20.10
# 25    17.9          17.90

我在这里创建了一个新列,以便于与原始数据进行比较。


更新

Markus 在评论中指出(感谢@markus)要重现您的预期输出,您实际上需要 method = "constant"f = 0.5:

weather %>%
    mutate(maxTemp_interp = approx(1:n(), maxTemp, 1:n(), method = "constant", f = 0.5)$y)
#    maxTemp maxTemp_interp
# 1     13.2          13.20
# 2     10.7          10.70
# 3       NA          14.30
# 4     17.9          17.90
# 5      6.6           6.60
# 6     10.0          10.00
# 7     13.0          13.00
# 8       NA          10.90
# 9       NA          10.90
# 10     8.8           8.80
# 11     9.9           9.90
# 12    14.9          14.90
# 13    16.3          16.30
# 14      NA          17.15
# 15    18.0          18.00
# 16     9.9           9.90
# 17    11.5          11.50
# 18    15.3          15.30
# 19    21.7          21.70
# 20    23.9          23.90
# 21    26.6          26.60
# 22    27.0          27.00
# 23    22.3          22.30
# 24      NA          20.10
# 25    17.9          17.90

如果您想使用最近的非 NA 值的平均值来回移动,您可以使用类似 data.table::nafill() 的东西来填充向下和向上的值,然后取平均值:

weather$prevTemp = data.table::nafill(weather$maxTemp, type = "locf")
weather$nextTemp = data.table::nafill(weather$maxTemp, type = "nocb")
weather$maxTemp[is.na(weather$maxTemp)] = ((weather$prevTemp + weather$nextTemp) / 2)[is.na(weather$maxTemp)]