在dplyr中的字符串列上过滤多个值


72

data.frame在其中一列中有一个字符数据。我想data.frame从同一列中过滤多个选项。有没有一种简单的方法可以做到这一点,而我却缺少了?

示例: data.frame名称=dat

days      name
88        Lynn
11          Tom
2           Chris
5           Lisa
22        Kyla
1          Tom
222      Lynn
2         Lynn

我想筛选出TomLynn例如。
当我做:

target <- c("Tom", "Lynn")
filt <- filter(dat, name == target)

我收到此错误:

longer object length is not a multiple of shorter object length

Answers:


199

您需要%in%代替==

library(dplyr)
target <- c("Tom", "Lynn")
filter(dat, name %in% target)  # equivalently, dat %>% filter(name %in% target)

产生

  days name
1   88 Lynn
2   11  Tom
3    1  Tom
4  222 Lynn
5    2 Lynn

要了解原因,请考虑此处发生的情况:

dat$name == target
# [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE

基本上,我们将两个长度target向量回收四次以匹配的长度dat$name。换句话说,我们正在做:

 Lynn == Tom
  Tom == Lynn
Chris == Tom
 Lisa == Lynn
 ... continue repeating Tom and Lynn until end of data frame

在这种情况下,我们没有收到错误,因为我怀疑您的数据框实际上有不同数量的行,这些行不允许回收,但是您提供的示例却有(8行)。如果样本的行数为奇数,我将得到与您相同的错误。但是,即使回收工作可行,这显然也不是您想要的。基本上,该语句dat$name == target等于说:

TRUE对于等于“ Tom”的每个奇数值或等于“ Lynn”的每个偶数值返回。

碰巧样本数据帧中的最后一个值是偶数且等于“ Lynn”,因此是TRUE上面的那个。

相比之下,dat$name %in% target说:

对于中的每个值dat$name,请检查中是否存在target

非常不一样。结果如下:

[1]  TRUE  TRUE FALSE FALSE FALSE  TRUE  TRUE  TRUE

请注意,您的问题与无关dplyr,只是对的滥用==


感谢您的解释布罗迪!真的很感激,临床医生试图找出R!
汤姆O

@BrodieG,您可以使用模式而不是完整字符串作为目标吗?
manabou11 '02

不能使用%in%,但是您可以在grepl("T[oi]m|lynne?", name)那里使用并使用所需的任何模式。
BrodieG '02

11

这可以使用CRAN中提供的dplyr软件包来实现。实现此目的的简单方法:

  1. 安装dplyr软件包。
  2. 运行以下代码
library(dplyr) 

df<- select(filter(dat,name=='tom'| name=='Lynn'), c('days','name))

说明:

因此,一旦我们下载了dplyr,就使用该包中的两个不同函数来创建一个新的数据框:

filter:第一个参数是数据帧;第二个参数是我们希望对其进行子集化的条件。结果是整个数据框只有我们想要的行。选择:第一个参数是数据帧;第二个参数是我们要从中选择的列的名称。我们不必使用names()函数,甚至不必使用引号。我们仅将列名作为对象列出。


10

使用base包装:

df <- data.frame(days = c(88, 11, 2, 5, 22, 1, 222, 2), name = c("Lynn", "Tom", "Chris", "Lisa", "Kyla", "Tom", "Lynn", "Lynn"))

# Three lines
target <- c("Tom", "Lynn")
index <- df$name %in% target
df[index, ]

# One line
df[df$name %in% c("Tom", "Lynn"), ] 

输出:

  days name
1   88 Lynn
2   11  Tom
6    1  Tom
7  222 Lynn
8    2 Lynn

使用sqldf

library(sqldf)
# Two alternatives:
sqldf('SELECT *
      FROM df 
      WHERE name = "Tom" OR name = "Lynn"')
sqldf('SELECT *
      FROM df 
      WHERE name IN ("Tom", "Lynn")')

1
 by_type_year_tag_filtered <- by_type_year_tag %>%
      dplyr:: filter(tag_name %in% c("dplyr", "ggplot2"))

2
尽管此代码可以提供问题的解决方案,但强烈建议您提供有关此代码为何和/或如何回答问题的其他上下文。从长远来看,只有代码的答案通常变得毫无用处,因为遇到类似问题的未来观看者将无法理解解决方案背后的原因。
palasas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.