我有一个数据框,其中包含一个变量,其中包含与其他变量中的元素匹配时要删除的元素-请参见下面的一个小示例:
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做到这一点的方法?
答案 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