Проблема
Я пытаюсь использовать dplyr::mutate()
и dplyr::case_when()
для создания нового столбца данных в кадре данных, который заполняется данными, хранящимися в другом объекте («список поиска»), иосновывается на информации в столбцах в кадре данных.
Я знаю, что ответ, вероятно, связан с (им) правильным использованием квазиквотирования и NSE, но у меня возникают проблемы с экстраполяцией информации в Программирование с dplyr
виньетка на мойситуация.
Я надеюсь, что публикация этого репертуара может привести меня к правильному ответу, и я думаю, что решение этой проблемы во многом поможет мне разобраться с NSE.
Пример данных
key_list <- list(
"a" = list(
foo = 1,
bar = 2),
"b" = list(
foo = 3,
bar = 4),
"c" = list(
foo = 5,
bar = 6)
)
x <- tibble(fruit = c("apple", "orange", "grape", "apple", "apple", "orange"),
`Old Letter` = c("a", "a", "b", "c", "c", "c"),
`Old Number` = c(9, 8, 7, 6, 5, 4)
)
x
# # A tibble: 6 x 3
# fruit `Old Letter` `Old Number`
# <chr> <chr> <dbl>
# 1 apple a 9
# 2 orange a 8
# 3 grape b 7
# 4 apple c 6
# 5 apple c 5
# 6 orange c 4
Цель
В частности, я хочу создать новый столбец в x
(который я назову `New Number`
), который заполняется на основе значений в x$fruit
и x$`Old Letter`
.
Вот код, который имитирует, где я зависаю в моем фактическом случае использования:
x %>% mutate(`New Number` = case_when(
fruit == "apple" ~ pluck(key_list, `Old Letter`, "foo") * 10,
fruit == "orange" ~ pluck(key_list, `Old Letter`, "foo") * 100,
fruit == "grape" ~ pluck(key_list, `Old Letter`, "foo") * 1000
))
# Error: Index 1 must have length 1, not 6
Ожидаемый результат
В моем представлении я вижу (требуемый) порядок таких операций, например, для первой строки x
:
fruit == "apple"
равен TRUE, поэтому оцените это выражение: pluck(key_list, `Old Letter`, "foo") * 10
- Поскольку значениев столбце
`Old Letter`
для этой строки "a"
выражение становится pluck(key_list, "a", "foo") * 10
(которое должно работать с объектом key_list
в глобальной среде) - Это упрощается до
2 * 10
, что равно 20
- Поместите результат вычисления этого выражения в столбец
`New Number`
.
Экстраполируя это на всю команду, я ожидал, что это будет выглядеть как:
# # A tibble: 6 x 4
# fruit `Old Letter` `Old Number` `New Number`
# <chr> <chr> <dbl> <dbl>
# 1 apple a 9 20
# 2 orange a 8 200
# 3 grape b 7 4000
# 4 apple c 6 60
# 5 apple c 5 60
# 6 orange c 4 600
Мой дубль:
Судя по полученному сообщению об ошибке, похоже, чтоодно значение из столбца `Old Letter`
используется в качестве индекса для использования pluck()
, весь столбец `Old Letter`
передается как вектор. Я предполагаю, что это потому, что в соответствии с документацией для case_when()
:
case_when()
не является функцией eid.
Я пытался отследить, как это происходит, но стек трассировки, похоже, не помог мне, и завершение всей команды в rlang::qq_show()
или quo()
не показало мне, как интерпретировал Rкоманда относительно NSE, потому что они оба выдавали ту же ошибку.
Я экспериментировал с комбинациями:
quo()
, enquo()
, !!
, !!enquo()
(сокращено до {{}}
) и sym()
inприведенный выше код Reprex
, а также его обертывание в функцию, но он выдает ту же ошибку:
get_num <- function(x, y) purrr::pluck(key_list, x, y)
x %>% mutate(`New Number` = case_when(
fruit == "apple" ~ get_num(`Old Letter`, "foo") * 10,
fruit == "orange" ~ get_num(`Old Letter`, "foo") * 100,
fruit == "grape" ~ get_num(`Old Letter`, "foo") * 1000
))
# Error: Index 1 must have length 1, not 6
Этот ответ на другой вопрос по SO говорит мне, что
Полагаю, что вам не хватает в case_when()
того, что аргументы вычисляются сразу, а не в строке.
Но я не уверен, если / какэто относится к моей ситуации, поэтому я в растерянности.
В любом случае, спасибо за любую помощь, которую вы, ребята, можете оказать!
sessionInfo()
:
R version 3.6.0 (2019-04-26)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS 10.15
Matrix products: default
BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRlapack.dylib
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] rlang_0.4.1 readxl_1.3.1 forcats_0.4.0 stringr_1.4.0 dplyr_0.8.3 purrr_0.3.3 readr_1.3.1 tidyr_1.0.0 tibble_2.1.3
[10] ggplot2_3.2.1 tidyverse_1.2.1
loaded via a namespace (and not attached):
[1] Rcpp_1.0.2 cellranger_1.1.0 pillar_1.4.2 compiler_3.6.0 base64enc_0.1-3 tools_3.6.0 digest_0.6.22 zeallot_0.1.0 evaluate_0.14
[10] lubridate_1.7.4 jsonlite_1.6 lifecycle_0.1.0 nlme_3.1-141 gtable_0.3.0 lattice_0.20-38 pkgconfig_2.0.3 cli_1.1.0 rstudioapi_0.10
[19] yaml_2.2.0 haven_2.1.1 xfun_0.10 withr_2.1.2 xml2_1.2.2 httr_1.4.1 knitr_1.25 generics_0.0.2 vctrs_0.2.0
[28] hms_0.5.1 grid_3.6.0 tidyselect_0.2.5 glue_1.3.1 R6_2.4.0 fansi_0.4.0 rmarkdown_1.16 modelr_0.1.5 magrittr_1.5
[37] htmltools_0.4.0 backports_1.1.5 scales_1.0.0 rvest_0.3.4 assertthat_0.2.1 colorspace_1.4-1 utf8_1.1.4 stringi_1.4.3 lazyeval_0.2.2
[46] munsell_0.5.0 broom_0.5.2 crayon_1.3.4