如何用 R 中的先例值和后续值的平均值替换 NA 值

How to replace NA values with average of precedent and following values, in R

我目前有一个或多或少具有以下特征的数据集:

Country <- rep(c("Honduras", "Belize"),each=6)
Year <- rep(c(2010,2011,2012,2014,2015,2016),2)
Observation <- c(2, 5,NA, NA,2,3,NA, NA,2,3,1,NA)
df <- data.frame(Country, Year, Observation)

我想做的是找到一个 command/write 一个 函数,它只用 :

填充每个国家的 NA
  1. 如果 NA 观察是针对第一年 (2010) 的,则用下一个非 NA 观察填充它;

  2. 如果 NA 观察是针对去年 (2014) 的,则用上一个可用期间的观察填充它。

3.1 如果 NA 观察是第一次和最后一次填充之间的年份,则为 2 个最近时期的平均值。

3.2 但是,如果有2个或多个连续的NA,(以2为例)先用前面的Observation填充第一个,用与(3.1)相同的方法填充第二个

作为示例,之前的数据集最终应该是:

Observation2 <- c(2, 5, 5, 3.5 ,2,3,2, 2,2,3,1,1)
df2 <- data.frame(Country, Year, Observation2)

希望我说得足够清楚。说的很具体,希望有人能帮忙。

有不明白的地方欢迎提问

输入。有一些问题是,问题下的评论中提到的和最后注释中显示的国家名称的交替是否是有意的,但无论如何假设增加年份的每个子序列都是一个单独的组,grp。 (如果 Country 的前 6 个条目是洪都拉斯,最后 6 个是伯利兹,那么我们可以在下面的代码中将 group_by(...) 替换为 group_by(Country)。)

澄清问题。我们假设问题是在组内询问:

  1. 前导 NA 将替换为第一个 non-NA。
  2. 尾随的 NA 将替换为最后一个 non-NA。
  3. 如果有一个连续的 NA 被 non-NA 包围,它将被前面的 non-NA 替换。
  4. 如果有两个连续的 NA,则第一个被替换为先前的 non-NA,第二个被替换为先前 non-NA 和下一个 non-NA 的平均值。
  5. 这个问题没有解决 3 个以上连续 NA 的情况,所以这可能永远不会发生,但以防万一它做了代码应该做的是用先前的 non-NA 和其余的填充第一个 NA应使用线性插值填充。

代码。现在对于每个组,将任何 NA 替换为先前的值。然后使用 rule=2 对通过 na.approx 剩下的内容使用线性插值来扩展末端。最后只保留需要的列。

dplyr 冲突。请注意,dplyr 中的 lag 和 filter 以不兼容的方式与 base R 中的同名函数发生冲突,因此我们排除它们并使用 dplyr:: prefix 如果我们想访问它们。

library(dplyr, exclude = c("lag", "filter"))
library(zoo)

df2 <- df %>%
  # group_by(Country) %>%
  group_by(grp = cumsum(c(TRUE, diff(Year) < 0))) %>%
  mutate(Observation2 = coalesce(Observation, dplyr::lag(Observation)) %>%
                          na.approx(rule = 2)) %>%
  ungroup %>%
  select(Country, Year, Observation2)

identical(df2$Observation2, Observation2)
## [1] TRUE

备注

我们使用了从问题中获取的输入。

Country <- rep(c("Honduras", "Belize"),6)
Year <- rep(c(2010,2011,2012,2014,2015,2016),2)
Observation <- c(2, 5,NA, NA,2,3,NA, NA,2,3,1,NA)
df <- data.frame(Country, Year, Observation)

df

给予:

    Country Year Observation
1  Honduras 2010           2
2    Belize 2011           5
3  Honduras 2012          NA
4    Belize 2014          NA
5  Honduras 2015           2
6    Belize 2016           3
7  Honduras 2010          NA
8    Belize 2011          NA
9  Honduras 2012           2
10   Belize 2014           3
11 Honduras 2015           1
12   Belize 2016          NA

已添加

发帖者在评论中又添加了一个例子。我们运行就在这里。这与上面第一段中讨论的 group_by 的简化代码相同。 (这不会改变结果。)

Country <- rep(c("Honduras", "Belize"),each=6) 
Year <- rep(c(2010,2011,2012,2014,2015,2016),2) 
Observation <- c(2, 5, NA, NA,2,3, NA, NA,2, NA,1,NA)
df <- data.frame(Country, Year, Observation)

df2 <- df %>%
  group_by(Country) %>%
  mutate(Observation2 = coalesce(Observation, dplyr::lag(Observation)) %>%
                          na.approx(rule = 2)) %>%
  ungroup %>%
  select(Country, Year, Observation2)

df2

给予:

# A tibble: 12 x 3
   Country   Year Observation2
   <chr>    <dbl>        <dbl>
 1 Honduras  2010          2  
 2 Honduras  2011          5  
 3 Honduras  2012          5  
 4 Honduras  2014          3.5
 5 Honduras  2015          2  
 6 Honduras  2016          3  
 7 Belize    2010          2  
 8 Belize    2011          2  
 9 Belize    2012          2  
10 Belize    2014          2  
11 Belize    2015          1  
12 Belize    2016          1