簡體   English   中英

如何通過包含 NA 作為級別的因子過濾 data.frame

[英]How to filter data.frame by a factor that includes NA as level

如果您的data.frame的因素不包括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))
#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$a的level是否為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)。

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

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

我同意is.na()不響應因素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)),]

使用 dplyr 和 %in% 運算符的簡單方法是:

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

正如這里的人們所提到的,R 中的 NA 匹配可能有點有趣。 “%in% 技巧”提供了更寬松的匹配,但恐怕我無法解釋其中的來龍去脈。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM