当我使用filter
中的dplyr
时,我很难理解R如何处理AND和OR运算符。
以下是一个例子:
library(dplyr)
xy <- data.frame(x=1:6, y=c("a", "b"), z= c(rep("d",3), rep("g",3)))
> xy
x y z
1 1 a d
2 2 b d
3 3 a d
4 4 b g
5 5 a g
6 6 b g
使用filter
我想删除x==1
和 z==d
的所有行。这会让我相信我想使用AND运算符:&
> filter(xy, x != 1 & z != "d")
x y z
1 4 b g
2 5 a g
3 6 b g
但这会删除所有包含x==1
或 z==d
的行。更令人困惑的是,当我使用OR运算符时,|
我得到了所需的结果:
> filter(xy, x != 1 | z != "d")
x y z
1 2 b d
2 3 a d
3 4 b g
4 5 a g
5 6 b g
此外,这确实有效,但如果我在同一个条件评估中将==
和!=
串在一起,则不是很理想。
> filter(xy, !(x == 1 & z == "d"))
x y z
1 2 b d
2 3 a d
3 4 b g
4 5 a g
5 6 b g
有人可以解释我错过的内容吗?
答案 0 :(得分:6)
这是布尔代数的问题。逻辑表达式!(x == 1 & z == d)
等同于x != 1 | z != d
,与-(x + y)
相同,等同于-x - y
。取消括号后,您将所有==
更改为!=
,将所有&
更改为|
,反之亦然。这导致了
!(x == 1 & z == "d")
与
不同x != 1 & z != "d"
而是
x != 1 | z != "d"
答案 1 :(得分:2)
一些不适合评论的提示:
如果您无法理解R中的某些内容是如何工作的,我强烈建议您运行每个单独的操作。使用dplyr
,可以轻松跟踪中间步骤并显示所有步骤:
mutate(xy,
A = x != 1,
B = z != 'd',
A_and_B = A & B,
A_or_B = A | B
)
# x y z A B A_and_B A_or_B
# 1 1 a d FALSE FALSE FALSE FALSE
# 2 2 b d TRUE FALSE FALSE TRUE
# 3 3 a d TRUE FALSE FALSE TRUE
# 4 4 b g TRUE TRUE TRUE TRUE
# 5 5 a g TRUE TRUE TRUE TRUE
# 6 6 b g TRUE TRUE TRUE TRUE
我认为,如果你看一下每一列的定义,它的价值就会非常有意义。然后,在一步一步之后,希望结果也是有意义的。
正如其他人已经以各种方式陈述的那样,你从一开始就为自己做好准备
使用过滤器我想要消除x == 1和z == d
的所有行
不要将filter
视为消除行,将其视为保留行。如果您在心理上将您的目标反转为“将所有行保留在哪里......”,您就可以自行设置单词到代码的直接翻译。
答案 2 :(得分:1)
filter
的结果是行,其中指定的条件为真。
以x != 1 & z != "d"
为例。这种情况属实的行是什么?你得到的输出。其他行已被删除,因为这些行的条件不正确。
在此示例中,您的真实目的是消除x == 1 and z == "d"
中的行。
换句话说,您希望保留条件x == 1 and z == "d"
为假的行。
将其放入代码成为filter(xy, !(x == 1 and z == "d"))
。
具有讽刺意味的是,这看起来很像你的意图,与你实际尝试写的非常不同。
如果你忘记filter
的逻辑,
您可以通过一个更简单的实验提醒自己,filter(xy, TRUE)
将返回所有行,filter(xy, FALSE)
将返回任何行。
答案 3 :(得分:1)
# x != 1 & z != "d" evaluates to a single TRUE/FALSE vector which subsets the data
# note how & and | behave in isolation:
TRUE & TRUE # T AND T = T
## [1] TRUE
TRUE & FALSE # T AND F = F
## [1] FALSE
FALSE & FALSE # F AND F = F
## [1] FALSE
TRUE | TRUE # T OR T = T
## [1] TRUE
TRUE | FALSE # T OR F = T
## [1] TRUE
FALSE | FALSE # F OR F = F
## [1] FALSE
# Apply over vectors
(x1 <- xy$x != 1)
## [1] FALSE TRUE TRUE TRUE TRUE TRUE
(z1 <- xy$z != "d")
## [1] FALSE FALSE FALSE TRUE TRUE TRUE
x1 & z1 # you get last 3 rows
## [1] FALSE FALSE FALSE TRUE TRUE TRUE
x1 | z1 # you get all but 1st row (which contains 1 and d)
## [1] FALSE TRUE TRUE TRUE TRUE TRUE