dplyr: фильтр_ с условием не работает - PullRequest
0 голосов
/ 19 мая 2018

Вот мои данные:

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)

Я хочу использовать фильтр_, поскольку он принимает условие как символ.Если вы можете предложить фильтр (без версии с подчеркиванием) и взять символ в качестве условия, это также будет работать.

Ответы [ 3 ]

0 голосов
/ 19 мая 2018

Другие объяснили причину этой проблемы, которая 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
0 голосов
/ 19 мая 2018

Код в виде строки является анти-шаблоном.Возникает вопрос: откуда взялась строка?

Если вы, разработчик, печатаете его, то писать его сложнее (вам не нужны такие функции IDE, как автозаполнение), и гораздо более подвержены ошибкам (вы можете писать синтаксическиневерный код, который не будет перехвачен до того, как он будет фактически проанализирован и оценен, возможно, намного позже, что усложнит понимание ошибок).

Если это ввод пользователя, который не является вами, это серьезная дыра в безопасности.

Вместо этого вы можете сделать следующее:

remove2 <- quote(as.numeric(as.character(A)) != 2L)

filter(df, !! remove2)

(!! - это оператор "unquote" в структуре tidyeval).

Хотя это не полностью удовлетворяет (все ещезапах кода, на мой взгляд), потому что редко приходится заключать в кавычки целые фрагменты кода, обычно это просто имя переменной.

0 голосов
/ 19 мая 2018

Попробуйте следующее:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...