通过匹配另一列来过滤一列

时间:2019-05-28 15:07:09

标签: r dplyr

我有一个数据框,其中包含一个变量,其中包含与其他变量中的元素匹配时要删除的元素-请参见下面的一个小示例:

df <- data.frame(pair = c(1, 1, 2, 2, 3, 3),
                 animal = rep(c("dog", "cat"), 3), 
                 value = seq(1, 12, 2), 
                 drop = c("no", "no", "dog", "dog", "cat", "cat"))

  pair animal value drop
1    1    dog     1   no
2    1    cat     3   no
3    2    dog     5  dog
4    2    cat     7  dog
5    3    dog     9  cat
6    3    cat    11  cat

我试图根据animal的值是否与drop的值匹配来过滤数据帧。我想要类似filter(df, animal != drop)的东西来删除仅动物值与drop值匹配的行:

  pair animal value drop
1    1    dog     1   no
2    1    cat     3   no
4    2    cat     7  dog
5    3    dog     9  cat

我还尝试编写一个简单的循环来测试动物匹配是否每行都下降,如果为true,则删除该行,但是我无法使其工作。 (我对循环不是很自信,并且如果可能的话,我不愿使用一个循环,因为我的数据帧很大,但是我感到绝望了!)

for(i in nrow(df)){
  if(df$animal[i] == df$drop[i]){
    df <- df[-i,]
    return(df)
  }
}

是否有使用dplyr做到这一点的方法?

2 个答案:

答案 0 :(得分:3)

一种选择是将character转换为mutate_at类,然后在不匹配的元素上使用filter

library(dplyr)
df %>% 
  mutate_at(vars(animal, drop), as.character) %>%       
  filter(animal != drop)
#  pair animal value drop
#1    1    dog     1   no
#2    1    cat     3   no
#3    2    cat     7  dog
#4    3    dog     9  cat

答案 1 :(得分:3)

使用filter(df, animal != drop)是正确的。但是,由于您没有在stringsAsFactors = F调用中指定data.frame(),因此所有字符串都将转换为因数,从而增加了不同级别集的错误。因此,添加stringsAsFactors = F应该可以解决此问题

df <- data.frame(pair = c(1, 1, 2, 2, 3, 3),
                 animal = rep(c("dog", "cat"), 3), 
                 value = seq(1, 12, 2), 
                 drop = c("no", "no", "dog", "dog", "cat", "cat"),
                 stringsAsFactors = F) 

df %>%
  filter(animal != drop)

  pair animal value drop
1    1    dog     1   no
2    1    cat     3   no
3    2    cat     7  dog
4    3    dog     9  cat

为避免使用此不希望出现的字符串来影响行为,我强烈建议使用tibble

如果没有机会更改数据的创建方式,我在这里提供@akrun的解决方案:

library(dplyr)

df %>% 
  mutate_at(vars(animal, drop), as.character) %>%       
  filter(animal != drop)
#  pair animal value drop
#1    1    dog     1   no
#2    1    cat     3   no
#3    2    cat     7  dog
#4    3    dog     9  cat
相关问题