这是我的数据:
df <- tibble::tribble(
~A, ~B, ~C, ~D,
2L, "a", "e", 2L,
4L, "a", "f", NA_integer_,
4L, "b", "g", NA_integer_,
4L, "b", "h", NA_integer_
)
df$B <- as.factor(df$B)
df$A <- as.factor(as.character(df$A))
以下是我的过滤条件:
remove2 <- "as.integer(A)!=2L"
我只想用A == 2删除观察结果,但是下面的代码保留了它,为什么?
df %>% dplyr::filter_(remove2)
我想使用filter_,因为它接受条件作为字符。如果您可以建议过滤(不使用下划线版本)并将字符作为条件,那也可以。
答案 0 :(得分:3)
尝试以下方法:
remove2 <- "as.numeric(as.character(A))!=2L"
df %>% dplyr::filter_(remove2)
# A tibble: 3 x 4
A B C D
<fct> <fct> <chr> <int>
1 4 a f NA
2 4 b g NA
3 4 b h NA
请注意,因素的编码方式不同。参见
as.integer(df$A)
[1] 1 2 2 2
要获取“如图所示”的因子值,请使用as.numeric(as.character(.))
其他答案指出,下划线功能已被弃用(尽管它们仍然有效)。为了以绝对未来的方式实现这一目标,使用简单的base
R:
df[which(df[["A"]] != 2L),]
# A tibble: 3 x 4
A B C D
<fct> <fct> <chr> <int>
1 4 a f NA
2 4 b g NA
3 4 b h NA
答案 1 :(得分:3)
作为字符串的代码是反模式。它提出了一个问题:字符串来自哪里?
如果是你,开发人员,输入它,那么编写起来就更困难了(你没有受益于你的IDE功能,比如自动完成),而且更容易出错(你可以写出语法上无效的代码,在它实际被解析和评估之前不会被捕获,可能更晚,更难以理解错误)。
如果是来自不是你的用户的输入,那么这是一个主要的安全漏洞。
你可以改为:
remove2 <- quote(as.numeric(as.character(A)) != 2L)
filter(df, !! remove2)
(!!
是tidyeval框架中的“unquote”运算符。)
虽然它不完全令人满意(在我看来仍然是代码味道),因为很少必须取消引用整个代码段,通常它只是一个变量名。
答案 2 :(得分:2)
其他人已经解释了这个问题的原因,factor
内部被编码为整数,这可能与它看起来很明显不同。我要指出的另一件事是filter_
自dplyr
0.7以来已被弃用。因此,我们可以考虑使用filter
函数将字符串评估为以下两个选项。
remove2 <- "as.integer(as.character(A)) != 2L"
library(dplyr)
library(rlang)
df %>% filter(eval(parse(text = remove2)))
# # A tibble: 3 x 4
# A B C D
# <fct> <fct> <chr> <int>
# 1 4 a f NA
# 2 4 b g NA
# 3 4 b h NA
df %>% filter(eval(parse_expr(remove2)))
# # A tibble: 3 x 4
# A B C D
# <fct> <fct> <chr> <int>
# 1 4 a f NA
# 2 4 b g NA
# 3 4 b h NA