填充面板数据中的NA值

时间:2017-01-18 11:16:32

标签: r merge aggregate

我有一个包含NA值的面板数据。我想用其他数据的值来填写NA。假设我想用panel完成以下new.df

panel <- data.frame("time" = c(rep(2000,5), rep(2001,5)), 
                    "var1" = rep(1:5, times=2), 
                    "var2" = c(NA,'b','c',NA,'d','a1','b1','c1',NA,'d1'))

new.df <- data.frame("time" = c(2000:2001), 
                     "var1" = c(4,4), 
                     "var2" = c('e','e'))

我尝试了merge / aggregate / ddplyr等的不同组合。问题是mergemerge.data.frame创建了由.x.y索引的其他列,即使是姓氏是完全相同的。

> merge(panel,new.df,by = c("time","var1"), all=T)
   time var1 var2.x var2.y
1  2000    1   <NA>   <NA>
2  2000    2      b   <NA>
3  2000    3      c   <NA>
4  2000    4   <NA>      e
5  2000    5      d   <NA>
6  2001    1     a1   <NA>
7  2001    2     b1   <NA>
8  2001    3     c1   <NA>
9  2001    4   <NA>      e
10 2001    5     d1   <NA>

我还尝试使用na.action选项但没有成功,因为合并后面板仍然不完整,剩余的NA必须保持不变。 (根据配方的不同,NA治疗在某些情况下将NA替换为0NaN

我想找到一种方法来定位面板中的正确索引,以便在其正确的位置“插入”new.df$var2,因为我知道我有一个非常大的面板,并且最后它将保持不完整。 / p>

提前致谢。

3 个答案:

答案 0 :(得分:2)

我们可以使用coalesce

中的tidyr
library(tidyr)
library(dplyr)
full_join(as.data.frame(panel),as.data.frame(new.df),by = c("time","var1")) %>% 
       mutate_each(funs(as.character), var2.x:var2.y) %>%
       mutate(var2= coalesce(var2.x, var2.y)) %>% 
       select(-var2.x, -var2.y)
#   time var1 var2
#1  2000    1 <NA>
#2  2000    2    b
#3  2000    3    c
#4  2000    4    e
#5  2000    5    d
#6  2001    1   a1
#7  2001    2   b1
#8  2001    3   c1
#9  2001    4    e
#10 2001    5   d1

或者我们可以在base R使用max.col选项。这里,'d1'是OP的输出merge

 d1$var2 <-d1[,3:4][cbind(1:nrow(d1), max.col(!is.na(d1[3:4]), "first"))]
 d1$var
 #[1] NA   "b"  "c"  "e"  "d"  "a1" "b1" "c1" "e"  "d1"

答案 1 :(得分:1)

将数据重新创建为数据框

library(dplyr)
panel <- data_frame("time" = c(rep(2000,5), rep(2001,5)), 
                    "var1" = rep(1:5, times=2), 
                    "var2" = c(NA,'b','c',NA,'d','a1','b1','c1',NA,'d1'))

new.df <- data_frame("time" = c(2000:2001), 
                     "var1" = c(4,4), 
                     "var2" = c('e','e'))

解决方案1使用基本R合并

填充NA值
panelnew <- merge(panel,new.df,by = c("time","var1"), all=T)
panelnew$var2 <- ifelse(is.na(panelnew$var2.x), panelnew$var2.y, panelnew$var2.x)
panelnew[c("time","var1","var2")]
   time var1 var2
1  2000    1 <NA>
2  2000    2    b
3  2000    3    c
4  2000    4    e
5  2000    5    d
6  2001    1   a1
7  2001    2   b1
8  2001    3   c1
9  2001    4    e
10 2001    5   d1

解决方案2使用dplyr left_join和mutate

填充NA值

这里我使用dplyr left_join加入新值。如果您还想添加原始面板中不存在的时间和var1的组合,请使用full_join。您将获得列var2.xvar2.y列,这是正常的,因为它反映了存在旧值和新值的事实。然后变异以用新值替换NA值。

result <- panel %>% 
    left_join(new.df, by = c("time", "var1")) %>% 
    mutate(var2 = ifelse(is.na(var2.x),var2.y,var2.x))

然后,如果您只想保留感兴趣的列

result <- result %>% select(time, var1, var2)

如果新值替换现有值,您打算做什么? 上面的代码将保留旧值。

答案 2 :(得分:1)

或者简单地说(假设new.df中的所有值都映射到Panel中相应的NA值):

ind <- which(paste0(panel[,1],panel[,2]) %in% paste0(new.df[,1],new.df[,2]))
panel[ind,3] = new.df[,3]