如何将NA值替换为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)

我想做的是找到一个命令/编写函数,该函数只用:填充每个国家的NA

  1. 如果NA观察是第一年(2010年(,则用下一个非NA观察填充;

  2. 如果NA观测是针对最后一年(2014年(的,则将其填入上一可用期间的观测。

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

3.2然而,如果有2个或多个连续的NA,(以2个为例(首先用前面的观测值填充第一个,用与(3.1(相同的方法填充第二个

举例来说,以前的数据集最终应该是:

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

我希望我已经足够清楚了。这很具体,但我希望有人能帮忙。

如果你不理解,可以随意提出任何问题。

输入。有一个问题是,是否有意更改该问题下的评论中提到的国家名称以及最后的说明中所示的国家名称,但无论如何,假设每一个年份增加的子序列都是一个单独的组和组,即grp。(如果国家的前6个条目是洪都拉斯,最后6个是伯利兹,那么我们可以在下面的代码中用group_by(国家(替换group_by。(

问题澄清。我们假设问题是在集团内部提出的:

  1. 将用第一个非NA替换主要NA
  2. 后面的NA将替换为最后一个非NA
  3. 如果存在一个被非NA包围的连续NA,则将其替换为先前的非NA
  4. 如果存在两个连续的NA,则第一个用先前的非NA代替,第二个用先前非NA和下一个非NA的平均值填充
  5. 这个问题并没有解决3+个连续NA的情况,所以这可能永远不会发生,但只是在它发生的情况下,代码应该做的是用之前的非NA填充第一个NA,其余部分应该使用线性插值填充

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

dplyr冲突。请注意,dplyr中的滞后和过滤器与基R中同名的函数以不兼容的方式冲突,因此我们将它们排除在外,如果我们想访问它们,则使用dplyr::前缀。

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  

最新更新