【问题标题】:Filling missing levels填补缺失的关卡
【发布时间】:2018-06-04 11:24:58
【问题描述】:

我有以下类型的数据框:

Country <- rep(c("USA", "AUS", "GRC"),2)
Year    <- 2001:2006
Level   <- c("rich","middle","poor",rep(NA,3))
df <- data.frame(Country, Year,Level)

df 
Country Year  Level
1     USA 2001   rich
2     AUS 2002 middle
3     GRC 2003   poor
4     USA 2004   <NA>
5     AUS 2005   <NA>
6     GRC 2006   <NA>

我想用右列最后一个正确的级别标签填充缺失值。

所以预期的结果应该是这样的:

Country Year  Level
1     USA 2001   rich
2     AUS 2002 middle
3     GRC 2003   poor
4     USA 2004   rich
5     AUS 2005 middle
6     GRC 2006   poor

【问题讨论】:

标签: r missing-data


【解决方案1】:

我们可以按“国家”分组并获得非NA唯一值

library(dplyr)
df %>%
    group_by(Country) %>% 
    dplyr::mutate(Level = Level[!is.na(Level)][1])
# A tibble: 6 x 3
# Groups:   Country [3]
#  Country  Year  Level
#   <fctr> <int> <fctr>
#1     USA  2001   rich
#2     AUS  2002 middle
#3     GRC  2003   poor
#4     USA  2004   rich
#5     AUS  2005 middle
#6     GRC  2006   poor

如果我们已经加载了dplyrplyr,最好明确指定dplyr::mutatedplyr::summarise,以便它使用来自dplyr 的函数。 plyr 中有相同的函数,当两者都加载创建不同的行为时,它可能会掩盖来自 dplyr 的函数。

【讨论】:

  • 好主意。好工作。但是我们不是在这里假设总会有一个非 na 唯一值吗?只是想明白..
  • @AbdulRahmanK 谢谢,看来 OP 有一个独特的价值。如果有多个值,可能是mutate(Level = toString(unique(Level[!is.na(Level)])))
  • @akrun ,我认为您的回答无效。即使对于我提供的 MWE,结果也不是预期的。正因为如此 [1] 并将所有国家都映射到“富国”。试图找到解决方案,但到目前为止没有任何效果。
  • @msh855 不清楚。根据示例,它正在工作
  • @msh855 这是函数屏蔽其他函数的问题之一。包plyrsummarise/mutate 等可以掩盖这个dplyr summarise/mutate,当你调用它时,它可能会调用plyr mutate。最好使用dplyr:: 来指定您想要该包中的功能。
【解决方案2】:

这是另一个data.table 解决方案,它在加入时更新 使用从给定数据集本身创建的查找表

library(data.table)
setDT(df)[df[!is.na(Level)], on = .(Country), Level := Level][]
   Country Year  Level
1:     USA 2001   rich
2:     AUS 2002 middle
3:     GRC 2003   poor
4:     USA 2004   rich
5:     AUS 2005 middle
6:     GRC 2006   poor

【讨论】:

    【解决方案3】:

    在基础 R 中,您可以使用 ave():

    transform(df, Level = ave(Level, Country, FUN = na.omit))
    
    #   Country Year  Level
    # 1     USA 2001   rich
    # 2     AUS 2002 middle
    # 3     GRC 2003   poor
    # 4     USA 2004   rich
    # 5     AUS 2005 middle
    # 6     GRC 2006   poor
    

    另一种更准确的可能性是使用连接。在这里,我们将Country 列与NA 省略的数据合并。结果是一样的,只是行顺序不同。

    merge(df["Country"], na.omit(df))
    
    #   Country Year  Level
    # 1     AUS 2002 middle
    # 2     AUS 2002 middle
    # 3     GRC 2003   poor
    # 4     GRC 2003   poor
    # 5     USA 2001   rich
    # 6     USA 2001   rich
    

    【讨论】:

    • 当我将它应用于我自己的数据帧时,我收到此错误消息“x[i]
    【解决方案4】:

    使用 的解决方案。

    library(dplyr)
    library(tidyr)
    
    df %>%
      arrange(Country) %>%
      fill(Level) %>%
      arrange(Year)
    #   Country Year  Level
    # 1     USA 2001   rich
    # 2     AUS 2002 middle
    # 3     GRC 2003   poor
    # 4     USA 2004   rich
    # 5     AUS 2005 middle
    # 6     GRC 2006   poor
    

    【讨论】:

    • strrep(字母[23], 3)
    • @AidanGawronski 酷!感谢分享。
    【解决方案5】:
    library(dplyr)
    
    df %>% 
      group_by(Country) %>% 
      mutate(Level = replace(Level, is.na(Level), unique(na.omit(Level))))
    
      Country  Year  Level
       <fctr> <int> <fctr>
    1     USA  2001   rich
    2     AUS  2002 middle
    3     GRC  2003   poor
    4     USA  2004   rich
    5     AUS  2005 middle
    6     GRC  2006   poor
    

    或者,更简洁地说,应用@suchait 的想法来使用na.locf

    df %>% 
      group_by(Country) %>% 
      mutate(Level = zoo::na.locf(Level))
    

    【讨论】:

      【解决方案6】:

      您可以使用data.tablezoo:-

      library(data.table)
      library(zoo)
      setDT(df)
      df[, Level := na.locf(Level), by = Country]
      

      这会给你:-

         Country Year  Level
      1:     USA 2001   rich
      2:     AUS 2002 middle
      3:     GRC 2003   poor
      4:     USA 2004   rich
      5:     AUS 2005 middle
      6:     GRC 2006   poor
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多