R: purrr Понимание функций извлечения purrr - PullRequest
0 голосов
/ 25 июня 2019

Вот простой вложенный список с тремя уровнями, уровень ob, каждый из которых содержит два списка v-уровня;уровень v, который содержит один или два объекта уровня s, и уровень s, каждый из которых содержит вектор символов.

test_lst <- list(ob1 = list(v1 = list(s1 = "X", s2 = paste0("A", 1:3)), v2 =  paste0("A", 4:8)), 
                 ob2 = list(v1 = list(s1 = "X", s2 = paste0("A", 9:11)), v2 =  paste0("A", 12:16)))

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

В файле справки по извлечению приводится пример использования извлечения по имени списка без имен на верхнем уровне.В этом примере функция извлечения пропускает верхний уровень и использует имена для поиска элементов на втором уровне.

l1 <- list(list(a = 1L), list(a = NULL, b = 2L), list(b = 3L))
l1 %>% map("a", .default = "???")

Второй пример не имеет имен и индексируется позиционно.Однако, опять же, позиции - это позиции в каждом элементе верхнего уровня списка.

l2 <- list(
 list(num = 1:3,     letters[1:3]),
 list(num = 101:103, letters[4:6]),
 list()
)
l2 %>% map(c(2, 2))

В первом примере выше предположим, что назван верхний уровень.Что происходит?

l1 <- list(one = list(a = 1L), two = list(a = NULL, b = 2L), three = list(b = 3L))
l1 %>% map("a", .default = "???")

Результат без изменений.Поэтому я ожидаю, что результат из

map(test_lst, c("v1", "s2"))

также пропустит имена верхнего уровня и вернет эквивалент

lapply(c("ob1", "ob2"), function(X)test_lst[[X]][["v1"]][["s2"]])

[[1]]
[1] "A1" "A2" "A3"

[[2]]
[1] "A9"  "A10" "A11

Но это не то, что происходит.Вместо этого

find_vars <- function(meta){
map_chr(meta, c("v1", "s2")) -> var_vecs
var_vecs
}

find_vars(meta = test_lst)

выдает следующую ошибку:

 Error: Result 1 must be a single string, not a character vector of length 3
Call `rlang::last_error()` to see a backtrace 
7. stop(cnd) 
6. abort(message, x = x, expected = expected, actual = actual, what = what, 
    arg = arg, ..., .subclass = c(.subclass, "purrr_error_bad_type")) 
5. stop_bad_type(x, expected, actual = actual, what = what, arg = arg, 
    recycle = recycle, message = message, .subclass = c(.subclass, 
        "purrr_error_bad_vector")) 
4. stop_bad_vector(x, expected_ptype, expected_length, what = what, 
    arg = arg, index = index, ..., recycle = recycle, message = message, 
    .subclass = c(.subclass, "purrr_error_bad_element_vector")) 
3. purrr:::stop_bad_element_vector(c("A1", "A2", "A3"), 1, character(0), 
    1, what = "Result", arg = NULL, recycle = FALSE) 
2. map_chr(meta, c("v1", "s2")) 
1. find_vars(meta = test_lst) 

> rlang::last_error()
<error>
message: Result 1 must be a single string, not a character vector of length 3
class:   `purrr_error_bad_element_vector`
backtrace:
 1. global::find_vars(meta = test_lst)
 3. purrr:::stop_bad_element_vector(...)
 4. purrr:::stop_bad_vector(...)
 5. purrr:::stop_bad_type(...)
Call `rlang::last_trace()` to see the full backtrace
> rlang::last_trace()
    x
 1. +-global::find_vars(meta = test_lst)
 2. | \-purrr::map_chr(meta, c("v1", "s2"))
 3. \-purrr:::stop_bad_element_vector(...)
 4.   \-purrr:::stop_bad_vector(...)
 5.     \-purrr:::stop_bad_type(...)

Я хотел бы понять:

  • почему я получаю ошибку;
  • что означает эта конкретная ошибка: и

  • как я могу получить результат, аналогичный приведенному выше lapply, используя purrr.

1 Ответ

0 голосов
/ 25 июня 2019

Если мы хотим извлечь, используйте pluck

pluck(test_lst, c("v1", "s2"))

Что касается error, map_chr ожидает возврата символа vector на основании документации

map_lgl (), map_int (), map_dbl () и map_chr () каждый возвращает атомный вектор указанного типа (или пытается умереть).

но вывод здесь - список. Рассмотрим следующий пример

map(test_lst, c("v1", "s2")) %>%
           map_chr(toString)
#         ob1            ob2 
#"A1, A2, A3" "A9, A10, A11" 

После извлечения компонентов в виде list, мы paste элементы в одну строку в пределах map_chr, и теперь он выравнивает его до vector. Но если намерение состоит в том, чтобы вернуть все как vector, это не позволит

map(test_lst, c("v1", "s2")) %>% 
        map_chr(I)

Ошибка: результат 1 должен быть одной строкой, а не вектором класса AsIs и длины 3 Позвоните rlang::last_error(), чтобы увидеть обратный след

...