объединить формулу и приборку eval (сюжетно) - PullRequest
2 голосов
/ 04 апреля 2019

Я изо всех сил пытаюсь понять это.

Ниже показано, как мне отфильтровать мой data.frame "аккуратно" и нарисовать график с использованием plotly.В этом случае я использую API на основе формул plotly, чтобы указать, какие столбцы фрейма данных использовать:

library(plotly)

tidy_filter = function(data, x) {
  x = enquo(x)
  filter(data, !!x > 5)
}

mtcars %>% 
  tidy_filter(wt) %>% 
  plot_ly(x = ~wt, y = ~wt)

Я могу обернуть это в одну функцию, чтобы получить тот же результат:

tidy_ply = function(data, x) {
  x = enquo(x)
  data = filter(data, !!x > 5)
  plot_ly(data, x = x, y = x)
}

tidy_ply(mtcars, wt)

Теперь:

  1. Я предполагаю, что enquo(x) в этом случае, по крайней мере, частично эквивалентен ~wt, так как это, похоже, работает.Но это две разные вещи (формула Quosure VS).Какая связь между ними и почему работает выше?

  2. Преимущество API формул plotly состоит в том, что если я хочу манипулировать входным значением, я могу делать что-то вроде ~wt/2.Но в приведенном выше примере plot_ly(data, x = x, y = x/2) выдает ошибку.Есть ли способ сделать эту работу?

Я предполагаю, что общий вопрос заключается в том, как наилучшим образом объединить подход аккуратного вычисления с подходом на основе формул сюжета?

1 Ответ

2 голосов
/ 04 апреля 2019

От этого ответа от @alistaire:

Пакет plotly R был создан немного раньше rlang и имеет свою собственную систему нестандартной оценки (NSE), которая, насколько я могу судить, в большинстве случаев документирована только в примерах.

Когда системы NSE идут вбок, самый быстрый способ заставить его работать - это динамически переписать весь код и затем оценить его. Здесь, оберните весь plotly конвейер в quo с заменой !! где угодно, затем вызовите quo_squash, чтобы свернуть его к одному выражению (вместо вложенных предложений), а затем вызовите eval_tidy для всего лота, чтобы фактически запустить его.

В plotly, ~ используется для ссылки на столбец в наборе данных для визуализации (@cpsievert).

В вашем примере x - это предложение, поэтому вы должны сначала заключить его в кавычки, прежде чем применять какой-либо базовый оператор. Вот что сообщило вам сообщение об ошибке:

Error: Base operators are not defined for quosures.
Do you need to unquote the quosure?

  # Bad:
  myquosure / rhs

  # Good:
  !!myquosure / rhs

Вот рабочее решение:

library(rlang)
library(plotly)

tidy_ply2 <- function(data, x) {
  x = enquo(x)
  print(x)

  data = filter(data, !!x > 5)

  # https://rlang.r-lib.org/reference/quasiquotation.html
  cat('\nUse qq_show() to debug the effect of unquoting operators\n')
  qq_show(plot_ly(data, x = ~!!x, y = ~!!x/2))

  # `base::eval` works too
  eval_tidy(
    quo_squash(
      quo({
        plot_ly(data, x = ~!!x, y = ~!!x/2)
      })
    )
  )
}

tidy_ply2(mtcars, wt)
#> <quosure>
#> expr: ^wt
#> env:  global
#> 
#> Use qq_show() to debug the effect of unquoting operators
#> plot_ly(data, x = ~^wt, y = ~(^wt) / 2)
#> 

Создано в 2019-04-03 пакетом Представить (v0.2.1.9000)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...