dplyr::filter使用逻辑变量筛选时是否会忽略缺失值?
dplyr::filter()对逻辑型变量缺失值的处理规则
dplyr::filter()执行筛选时,仅会保留条件表达式返回结果严格为TRUE的行,返回值为FALSE和NA的行都会被直接排除,不会默认保留缺失值对应的行,该逻辑和R基础逻辑索引规则一致。
我们可以通过示例验证具体效果:
无缺失值时的筛选表现
先构造无缺失的学生身高数据,计算转学学生的平均身高:
library(tidyverse, warn.conflicts = FALSE) set.seed(2423) small_tibble <- tibble(height = c(rnorm(n = 5, 56, 10), rnorm(n = 10, 46, 10), rnorm(n = 15, 66, 10)), transfer = c(rep(TRUE, 15), rep(FALSE, 15)) ) print(small_tibble, n = Inf) #> # A tibble: 30 x 2 #> height transfer #> <dbl> <lgl> #> 1 52.5 TRUE #> 2 59.9 TRUE #> 3 56.1 TRUE #> 4 50.5 TRUE #> 5 52.5 TRUE #> 6 53.1 TRUE #> 7 54.3 TRUE #> 8 40.7 TRUE #> 9 53.5 TRUE #> 10 49.3 TRUE #> 11 67.5 TRUE #> 12 53.3 TRUE #> 13 52.5 TRUE #> 14 25.7 TRUE #> 15 44.0 TRUE #> 16 70.9 FALSE #> 17 68.0 FALSE #> 18 59.2 FALSE #> 19 59.3 FALSE #> 20 64.9 FALSE #> 21 70.9 FALSE #> 22 63.3 FALSE #> 23 79.0 FALSE #> 24 69.4 FALSE #> 25 68.8 FALSE #> 26 76.0 FALSE #> 27 78.9 FALSE #> 28 62.4 FALSE #> 29 71.4 FALSE #> 30 77.2 FALSE janitor::tabyl(small_tibble, transfer) #> transfer n percent #> FALSE 15 0.5 #> TRUE 15 0.5 # 所有学生的平均身高 small_tibble %>% summarize(n(), mean(height)) #> # A tibble: 1 x 2 #> `n()` `mean(height)` #> <int> <dbl> #> 1 30 60.2 # 转学学生的平均身高 small_tibble %>% filter(transfer) %>% summarize(n(), mean(height)) #> # A tibble: 1 x 2 #> `n()` `mean(height)` #> <int> <dbl> #> 1 15 51.0
无缺失时筛选逻辑正常,15名转学学生全部被保留,得到的平均身高为51.0。
存在缺失值时的筛选影响
当我们把前5名学生的转学状态设为缺失值NA后:
small_tibble$transfer[1:5] <- NA janitor::tabyl(small_tibble, transfer) #> transfer n percent valid_percent #> FALSE 15 0.5000000 0.6 #> TRUE 10 0.3333333 0.4 #> NA 5 0.1666667 NA
此时再执行filter(transfer)筛选转学学生,前5行的NA会被判定为不符合筛选条件,和15行FALSE一起被排除,最终仅保留剩下的10行明确为TRUE的转学学生,计算得到的平均身高会和无缺失时的真实结果存在偏差:
small_tibble %>% filter(transfer) %>% summarize(n(), mean(height)) #> # A tibble: 1 x 2 #> `n()` `mean(height)` #> <int> <dbl> #> 1 10 49.4
缺失值处理方案
如果需要针对业务场景特殊处理缺失值,可以调整筛选逻辑:
- 把转学状态为NA的学生也计入转学群体:
filter(transfer | is.na(transfer)) - 明确仅保留明确为转学的学生,增加代码可读性:
filter(transfer == TRUE) - 先补全缺失值再筛选:
mutate(transfer = replace_na(transfer, FALSE))后再执行filter操作
内容的提问来源于stack exchange,提问作者phargart
相关产品推荐
相关产品推荐

