[英]dplyr: filter_ with character condition not working
這是我的數據:
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_,因為它接受條件作為字符。 如果您可以建議使用過濾器(沒有下划線版本)並以字符為條件,那也可以。
請嘗試以下操作:
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
其他人解釋這個問題的原因,這是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
代碼作為字符串是一種反模式。 這就提出了一個問題:字符串是從哪里來的?
如果是開發人員輸入您的姓名,那么編寫起來會更加困難(您無法從自動完成等IDE功能中受益),而且更容易出現錯誤(可以編寫語法上無效的代碼,不會在實際解析和評估之前被捕獲,可能要晚得多,這會導致難以理解的錯誤)。
如果是不是您的用戶輸入的,那將是一個重大的安全漏洞。
您可以改為:
remove2 <- quote(as.numeric(as.character(A)) != 2L)
filter(df, !! remove2)
( !!
是tidyeval框架中的“ unquote”運算符)。
盡管兩者都不盡如人意(在我看來,這仍然是代碼的味道),因為很少需要取消引用全部代碼,通常它只是一個變量名。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.