【问题标题】:How to filter data.frame by a factor that includes NA as level如何通过包含 NA 作为级别的因素过滤 data.frame
【发布时间】:2018-03-06 20:08:39
【问题描述】:

如果您有一个 data.frame 的因子不包括 NAs 作为级别,您可以毫无问题地过滤您的数据。

set.seed(123)
df=data.frame(a = factor(as.character(c(1, 1, 2, 2, 3, NA,3,NA)),exclude=NULL),
           b= runif(8))
#str(df)
df[df$a==3,]
#      a         b
#    5 3 0.9404673
#    7 3 0.5281055

如果您需要按 NA 级别过滤,则会出现这些问题。以下方法不起作用:

df[df$a==NA,]
df[df$a=="NA",]
df[is.na(df$a),]

我发现的唯一方法是将因子转换为数字并将其与级别数进行比较。

df[as.numeric(df$a)==4,]
#     a         b
#6 <NA> 0.0455565
#8 <NA> 0.8924190

还有其他更直观/优雅的方式来获得相同的结果吗?

【问题讨论】:

  • 好吧,df[df$a == factor(NA, levels=levels(df$a), exclude = NULL), ]

标签: r dataframe filtering


【解决方案1】:

使用 dplyr 和 %in% 运算符的简单方法是:

df %>%
  filter(
    a %in% NA_character_
  )
#>      a         b
#> 1 <NA> 0.0455565
#> 2 <NA> 0.8924190

正如这里的人们所提到的,R 中的 NA 匹配可能有点有趣。 “%in% 技巧”提供了更宽松的匹配,但恐怕我无法解释其中的来龙去脉。

【讨论】:

    【解决方案2】:

    如果您也有真正的缺失值(不属于因子的水平)...

    DF = data.frame(
      x = factor(c("A", "B", NA), levels=c("A", NA), exclude=NULL),
      v = 1:3
    )
    

    第 3 行的 x 具有级别 NA,而第 2 行是真正的缺失值。

    要获得第 3 行,您可以使用 data.table 进行连接...

    library(data.table)
    setDT(DF)
    
    merge(DF, data.table(x = factor(NA_character_, exclude=NULL)))
    # or
    DF[.(factor(NA_character_, exclude=NULL)), on=.(x), nomatch=0]    
    
    #     x v
    # 1: NA 3
    

    或者在 dplyr 中更尴尬:

    dplyr::right_join(DF, 
      data.frame(x = factor(NA_character_, levels=levels(DF$x), exclude=NULL)))
    
    # Joining, by = "x"
    #      x v
    # 1 <NA> 3
    

    除了疯子外,我找不到任何办法到基地这里来……

    wv = which(is.na(levels(DF$x)))
    DF[ !is.na(DF$x) & as.integer(DF$x) == wv, ]
    
    #      x v
    # 3 <NA> 3
    

    【讨论】:

      【解决方案3】:

      检查对应的df$a的等级是否为na:

      df[is.na(levels(df$a)[df$a]),]
           a         b
      6 <NA> 0.1649003
      8 <NA> 0.6556045
      

      正如弗兰克所指出的,这还包括df$a 的值(不仅仅是它的水平)是NA 的观察结果。我猜最初的海报想包括这些案例。如果没有,可以做类似的事情

      x <- factor(c("A","B", NA), levels=c("A", NA), exclude = NULL)
      i <- which(is.na(levels(x)[x]))
      i[!is.na(x[i])]
      

      给你3,只有NA-级别,忽略未知级别(B)。

      【讨论】:

      • 我对此表示赞同,但后来意识到它仍然为x = factor(c("A","B", NA), levels=c("A", NA), exclude = NULL) 返回错误的结果——应该只获得第三个元素,但is.na(levels(x)[x]) 也选择了第二个。
      • 你是对的。 ` as.integer(x)` 将给出[1] 1 NA 2,显然levels(x)[NA] 也是NA。感谢您的关注!
      【解决方案4】:

      我同意is.na() 不响应因素有点奇怪。但这似乎有效:

      set.seed(123)
      df=data.frame(a = factor(as.character(c(1, 1, 2, 2, 3, NA,3,NA)),exclude=NULL),
                    b= runif(8))
      df[is.na(as.character(df$a)),]
      

      【讨论】:

      • 如果你添加exclude=NULL 那么你所拥有的是有效值,只是级别是NA
      • 对。写完就想起来了:)
      • 是的,不幸的是 SO 鼓励“先发帖,后思考”的行为 ;-)
      猜你喜欢
      • 2022-11-22
      • 1970-01-01
      • 1970-01-01
      • 2011-06-30
      • 1970-01-01
      • 2016-08-23
      • 1970-01-01
      • 2012-02-06
      • 1970-01-01
      相关资源
      最近更新 更多