dplyr mutate: не удалось выполнить рекурсивное индексирование - PullRequest
0 голосов
/ 13 марта 2019

У меня проблема с mutate и самописной функцией. Мои данные в основном таковы:

license_sets <- list(x = c("A", "B"), y = c("C", "D", "E"))
license_data <- data.frame(license = c("A","B","C","D","E"), bidder = c("x","x","y","y","y"))
source_data <- expand.grid(license_i = c("A","B","C","D","E"), license_j = c("A","B","C","D","E"))
source_data$value <- c(1:25)

Функция, которую я хочу применить, выглядит следующим образом:

compute_set <- function(i, J){  tmp <- source_data %>% 
filter(license_i == i, license_j %in% J)
return(sum(tmp$value))
}

Теперь я хочу применить функцию с помощью mutate:

license_data %>% mutate(z = compute_set(license, license_sets[[bidder]]))

Я получаю следующие сообщения об ошибках и предупреждения:

Error in mutate_impl(.data, dots) : 
  Evaluation error: Evaluation error: recursive indexing failed at level 2
..
In addition: Warning messages:
1: In is.na(e1) | is.na(e2) :
  longer object length is not a multiple of shorter object length
2: In `==.default`(license_i, i) :
  longer object length is not a multiple of shorter object length

Если я запускаю ту же функцию с простым циклом for, она работает совершенно нормально. Кто-нибудь знает, в чем проблема (ы) здесь? Это должно быть связано с мутацией, верно? Я также уже попробовал as.character (покупатель) и другие вещи, которые я нашел здесь, но пока ничего не получалось. Я должен добавить, что фреймы данных, с которыми я имею дело, намного больше, чем те, которые я здесь показываю, поэтому цикл for невозможен ... (следовательно, я также благодарен за подсказки по упрощению для функции;))

1 Ответ

0 голосов
/ 13 марта 2019

Проблема в том, что в mutate аргументы всегда передаются как целые векторы, как вы можете видеть здесь:

license_data %>% mutate(z = {print(list(bidder, license));
                             compute_set(license, license_sets[[bidder]])})
# [[1]]
# [1] x x y y y
# Levels: x y
# [[2]]
# [1] A B C D E
# Levels: A B C D E
# Error in license_sets[[bidder]] : recursive indexing failed at level 2

Индексирование списка таким способом не работает:

license_sets[[license_data$bidder]]
# Error in license_sets[[license_data$bidder]] : 
#   recursive indexing failed at level 2

Итак, вы хотите map через векторы вместо:

license_data %>% 
  mutate(z = map2(bidder, license, ~ compute_set(.y, license_sets[[.x]])))

Векторизация

Как указывал @ [docendo discimus], проблема с вашей функцией заключается в том, что она не векторизована, то есть имеет дело (в случае i) только со скаляром. Вы можете векторизовать свою функцию для работы с ней как целое число:

compute_set_v <- Vectorize(compute_set)
license_data %>% 
   ## add the list content directly to the data frame 
   mutate(bidder_set = map(bidder, ~ license_sets[[.]]),
          z          = compute_set_v(license, bidder_set))

Примечание

data.frame имеет неприятную привычку рассматривать строки как факторы, поэтому вы можете добавить stringsAsFactors = FALSE в вашу data.frame конструкцию.

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