【问题标题】:dplyr::filter() behavior unexpected with NAsdplyr::filter() 行为与 NA 不同
【发布时间】:2020-08-01 15:42:03
【问题描述】:

我有以下两列的数据:

  • location_country:alpha-2 代码(例如,“US”)
  • location_admin_level_1: 行政级别 1('US' 应为 2 个字符)

一步,我filter() 出location_admin_level_1 字符数大于2:

librayr(dplyr)

data %>%
    filter(location_country == "US",
           nchar(location_admin_level_1) > 2)

...正常工作。

但是,当我尝试过滤这些 out(即,获取其余数据)时,它返回的行数少于应有的行数:

# Does not behave as expected
data %>%
    filter(!(location_country == "US" & nchar(location_admin_level_1) > 2))

这也行不通

# Does not behave as expected
data %>%
    filter(location_country != "US" | (location_country == "US" & nchar(location_admin_level_1) == 2))

但是当我使用 base R 过滤这些行时,它可以按预期工作:

# Works
data[data$location_country != "US" | (data$location_country == "US" & nchar(data$location_admin_level_1) == 2), ]

# Also works
data[!(data$location_country == "US" & nchar(data$location_admin_level_1) > 2), ]

为什么基本 R 解决方案可以按预期工作,而 dplyr 解决方案却不能?

(请注意:我无法创建 MWE,因为我不知道过滤行为是如何工作的,这是我的问题所关注的)

【问题讨论】:

  • @akrun,我无法创建 MWE,因为我不知道重新创建它的过滤行为(并且数据是 1000 万行)。对不起!
  • 我创建了一个可重现的示例并在下面发布了一个答案。它显示了单个 NA 的行为

标签: r dplyr


【解决方案1】:

一种可能性是这些行中存在NA 元素。 Base R 将返回 NA 行,因为 == 和 NA 返回 NA 而 filter 默认删除逻辑向量中的 NA

data[!(data$location_country == "US" & nchar(data$location_admin_level_1) > 2), ]

现在与filter 联系dplyr

library(dplyr)
data %>%
    filter(!(location_country == "US" & nchar(location_admin_level_1) > 2))

如果我们想获得filter 中的NA 行,请使用is.na

data %>% 
   filter((!(location_country == "US" & !is.na(location_country) &
        nchar(location_admin_level_1) > 2 &
           !is.na(location_admin_level_1)))|
           is.na(location_country))

问题是== 在有任何 NA 时返回 NA

with(data, location_country == "US")
#[1]  TRUE  TRUE FALSE FALSE    NA

在 base R 中,逻辑向量中的 NA 只返回 NA 行,因为它不是 TRUE 或 FALSE,而在 filter 中,默认情况下会删除它,在 filter 步骤中仅保留 2 行(只考虑最后一个表达式)。要使这个为真或假,只需添加一个is.na

with(data, location_country == "US" & !is.na(location_country))
#[1]  TRUE  TRUE FALSE FALSE FALSE

这将删除NA 行。但是,假设如果我们需要 NA 行,那么最后一个元素应该为 TRUE。为此我们需要|

with(data, location_country == "US"|is.na(location_country))
#[1]  TRUE  TRUE FALSE FALSE  TRUE

数据

data <- data.frame(location_country = c('US', 'US', 'China', 'Canada', NA), location_admin_level_1 = c('hello', 'l', 'w', '321', '2443'))

【讨论】:

  • 如果我取 location_county 为 NA、location_admin_level_1 为 NA 或两者均为 NA 的行数并从数据中的总行数中减去该行数,我仍然没有获取与我认为应该可以工作的过滤示例中返回的数据具有相同维度的数据
  • @Brigadeiro 在本例中,我展示了 location_country 为 NA 的情况,这将在逻辑输出中返回 NA 并带有== 即v1 &lt;- c(1, 2, 3); v1 == 1 并且子集为此提供了一个 NA 行。否则,我们需要通过is.na 来处理 NA
  • @Brigadeiro 你可以试试data %&gt;% filter(!(location_country == "US" &amp; !is.na(location_country) &amp; nchar(location_admin_level_1) &gt; 2 &amp; !is.na(location_admin_level_1))|is.na(location_country))
  • 知道了!非常感谢
猜你喜欢
  • 2022-11-09
  • 2015-05-05
  • 2019-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-21
  • 2016-07-20
相关资源
最近更新 更多