如何在dplyr过滤器中指定"不包含"的条件

80

我对R非常陌生。

使用名为SE_CSVLinelist_clean的表格,我想提取变量名为where_case_travelled_1且不包含字符串"Outside Canada""Outside province/territory of residence but within Canada"的行。然后创建一个名为SE_CSVLinelist_filtered的新表格。

SE_CSVLinelist_filtered <- filter(SE_CSVLinelist_clean, 
where_case_travelled_1 %in% -c('Outside Canada','Outside province/territory of residence but within Canada'))
上面的代码在我只使用"c"而不是"-c"时可行。那么,当我真正想要排除包含国外或省份之外内容的行时,我该如何指定上述内容?
答案: 上面的代码在只使用"c"而不是"-c"时可行。那么,当我真正想要排除包含国外或省份之外内容的行时,我该如何指定呢?

31
如果你发现自己经常想使用 "does not contain",那么你可能想要定义自己的函数。例如 \%notin%` = function(x,y) !(x %in% y)。然后你可以使用 x %notin% y代替!(x %in% y)`。 - eipi10
4个回答

120

请注意%in%返回一个由TRUEFALSE组成的逻辑向量。要对其取反,可以在逻辑语句前面使用!

SE_CSVLinelist_filtered <- filter(SE_CSVLinelist_clean, 
 !where_case_travelled_1 %in% 
   c('Outside Canada','Outside province/territory of residence but within Canada'))

关于您最初的做法,使用 -c(...)- 是一个一元运算符,它“对数字或复数向量(或可强制转换为它们的对象)执行算术操作”(来自 help("-"))。由于您正在处理无法强制转换为数字或复数的字符向量,因此不能使用 -


6

将搜索条件放在括号中,如下所示。这将返回括号内的条件查询结果。然后测试其结果,以确定它是否为负数(即它不属于向量中的任何选项),将其设置为FALSE。

SE_CSVLinelist_filtered <- filter(SE_CSVLinelist_clean, 
(where_case_travelled_1 %in% c('Outside Canada','Outside province/territory of residence but within Canada')) == FALSE)

3

仅需小心之前提供的解决方案,因为它们要求将您要检测的字符串完全打出。

请自问一下,例如单词 "Outside" 是否足够。如果是,则:

data_filtered <- data %>% 
  filter(!str_detect(where_case_travelled_1, "Outside")

一个可重复的示例版本:

iris

iris %>% 
  filter(!str_detect(Species, "versicolor"))

严格来说,这是一个stringr函数,而不是dplyr函数。但是它确实是tidyverse的一部分,并且是一个很好的解决方案。 - Vance Lopez
1
你也可以使用str_detect(...)而不是外部否定,参数设为negate = FALSE。 - polmonroig
@polmonroig 很棒,我不知道那个!我猜它们两个读起来很相似。"按物种过滤鸢尾花,以便不检测到包含“versicolor”字符串的结果。""按物种过滤鸢尾花,以便不检测到“versicolor”字符串的结果。" - gradcylinder

3

快捷修复。首先定义%in%的相反操作:

  '%ni%' <- Negate("%in%")

然后应用:

SE_CSVLinelist_filtered <- filter(
    SE_CSVLinelist_clean, 
    where_case_travelled_1 %ni% c('Outside Canada',
      'Outside province/territory of residence but within Canada'))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接