Проблема с именованным списком при использовании dplyr :: recode в purrr :: map2 - PullRequest
0 голосов
/ 06 декабря 2018

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

library(tidyverse)

my_data <- tribble(
  ~lookup_lists, ~old_vectors,

  # Observation 1
  list(
    "X1" = "one",
    "X7" = "two", 
    "X16" = "three"
  ), 

  c("Col1", "Col2", "Col3", "X1", "X7", "X16"),

  # Observation 2
  list(
    "X3" = "one",
    "X8" = "two", 
    "X22" = "three"
  ), 

  c("Col1", "Col2", "Col3", "X3", "X8", "X22")
)

На этом этапе я хочу создать новый столбец, который имеет те же векторные значения, что и old_vectors, но значения, начинающиеся с X , перекодируются, чтобы отразить поиск по именисписок в lookup_lists.Например, я хочу, чтобы первая строка перешла из:

c("Col1", "Col2", "Col3", "X1", "X7", "X16")

в

c("Col1", "Col2", "Col3", "one", "two", "three")

и была сохранена в новом столбцево вложенном тибле.Вот моя попытка использования функции map2:

# Add a third column that has the recoded vectors

my_data <- my_data %>%
  mutate(new_vectors = map2(.x = old_vectors, .y = lookup_lists, .f = ~recode(.x, .y)))

#> Error in mutate_impl(.data, dots): Evaluation error: Argument 2 must be named, not unnamed.

Я не понимаю этого, потому что назван второй аргумент IS .Вот первый lookup_list наблюдения, который показывает мою точку зрения:

my_data$lookup_lists[[1]]
$X1
[1] "one"

$X7
[1] "two"

$X16
[1] "three"

Я думаю, что упускаю что-то довольно очевидное и, вероятно, связано с this .Любая помощь будет принята с благодарностью!

Ответы [ 2 ]

0 голосов
/ 06 декабря 2018

Это не работает, потому что recode не работает таким образом.Чтобы понять, что происходит, это помогает упростить ваш пример:

x <- my_data[["old_vectors"]]
y <- my_data[["lookup_lists"]]
recode(x[[1]], y[[1]])
## Error: Argument 2 must be named, not unnamed

Как описано в ?recode, функция ожидает не именованный список замен, а ряд именованных аргументов.То есть вместо recode(x[[1]], y[[1]]) он хочет

recode(x[[1]], X1 = "one", X7 = "two", X16 = "three")
## [1] "Col1"  "Col2"  "Col3"  "one"   "two"   "three"

Эта ситуация распространена, и к ней существует стандартный подход:

invoke(recode, .x = y[[1]], x[[1]])
## [1] "Col1"  "Col2"  "Col3"  "one"   "two"   "three"

Теперь, когда мы знаем, как передатьименованный список аргументов функции, которая ожидает несколько (возможно именованных) аргументов, мы можем применить эти знания для решения исходной проблемы:

my_data <- my_data %>%
    mutate(new_vectors = map2(.x = old_vectors, .y = lookup_lists,
                              .f = ~invoke(recode, .x = .y, .x)))
0 голосов
/ 06 декабря 2018

Поскольку «lookup_lists» является именованным list, мы можем unlist преобразовать его в именованное vector, использовать его для сопоставления элементов в «old_vectors» и заменить на значения, соответствующие «ключу».с элементами в 'old_vector'.Те, которые не совпадают, будут NA.Удалите это с помощью na.omit и объедините с элементами 'Col' (используя grep) в 'old_vectors'

out <- my_data %>% 
           mutate(new_vectors = map2(old_vectors, lookup_lists,
         ~ c(grep('Col', .x, value = TRUE), unname(na.omit(unlist(.y)[.x])))))
out$new_vectors
#[[1]]
#[1] "Col1"  "Col2"  "Col3"  "one"   "two"   "three"

#[[2]]
#[1] "Col1"  "Col2"  "Col3"  "one"   "two"   "three"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...