【问题标题】:Filling NA values in a panel data在面板数据中填充 NA 值
【发布时间】:2017-06-02 17:57:08
【问题描述】:

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

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'))

我尝试了合并/聚合/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 处理将用0NaN 替换NA

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

提前致谢。

【问题讨论】:

  • 为什么要使用cbind 而不是data.frame 创建这些数据集?这是故意的吗?
  • 我建议您检查this 答案,因为它可以让您一次更新任意多的列。类似cols &lt;- setdiff(colnames(new.df), c("time", "var1")) ; library(data.table) ; setDT(panel)[setDT(new.df), (cols) := mget(paste0("i.", cols)), on = c("time", "var1")]

标签: r merge aggregate


【解决方案1】:

我们可以从tidyr使用coalesce

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"

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      将数据重新创建为数据框

      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)
      

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

      【讨论】:

      • 它可以工作,但我需要控制 ifelse 函数中的因素。谢谢!
      • “因素”是什么意思?阿克伦的回答中没有任何因素。方法不同,我不知道漂亮的coalesce 函数。但结果数据框与 Akrun 的答案相同。我猜你可能需要将你的 var2 列转换为字符变量,就像 Akrun 通过在 mutate 行之前添加这一行 mutate_each(funs(as.character), var2.x:var2.y) %&gt;% 所做的那样。但是,如果您首先不包括因素,仅通过创建字符变量,请参阅?data_frame,那么这不是必需的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-16
      • 2018-06-02
      相关资源
      最近更新 更多