Как переработать более короткие векторы в map2(), не используя rep()?

Вопрос или проблема

Я пытаюсь запустить следующий код:

xx <- 1:12
yy <- 1:3
map2(xx, yy, ~ .x / .y)

Однако я столкнулся с ошибкой. Я предполагал, что map2() автоматически будет перерабатывать более короткий вектор (то есть увеличивать длину yy, чтобы соответствовать xx), но, похоже, это не так.

Желаемый результат :

1
1
1
4
2.5
2
7
4
3
10
5.5
4

Существует ли способ заставить map2() автоматически обрабатывать переработку векторов без ручного использования rep()?

Вы можете использовать mapply() из базового R (вместо purrr::map2()):

mapply(\(.x, .y) .x / .y, xx, yy)
# или 
mapply(`/`, xx, yy)

#  [1]  1.0  1.0  1.0  4.0  2.5  2.0  7.0  4.0  3.0
# [10] 10.0  5.5  4.0

Мы можем использовать Map():

unlist(Map(`/`, xx, yy))

#>  [1]  1.0  1.0  1.0  4.0  2.5  2.0  7.0  4.0  3.0 10.0  5.5  4.0

Если вам действительно нужно использовать map2(), то мы можем сделать что-то вроде этого:

data.frame(xx, yy) %>% {map2(.$xx, .$yy, `/`)} %>% unlist()

#>  [1]  1.0  1.0  1.0  4.0  2.5  2.0  7.0  4.0  3.0 10.0  5.5  4.0

Я не уверен, зачем вам нужна функция map2, если / векторизована:

просто сделайте:

xx/yy
 [1]  1.0  1.0  1.0  4.0  2.5  2.0  7.0  4.0  3.0 10.0  5.5  4.0

Если функция не векторизована, векторизуйте её с помощью Vectorize, который переработает аргументы

Ответ или решение

Чтобы решить проблему с использованием функции map2() из пакета purrr, когда одна из векторов короче другого, и вы хотите избежать использования rep(), возможности действительно существуют, и они довольно просты.

Как вы уже заметили, map2() не выполняет автоматическую переработку более короткого вектора. Однако существуют другие методы, которые могут помочь вам достичь желаемого результата.

  1. Использование mapply():

Функция mapply() из базового R позволяет выполнять операцию с векторами разной длины, используя переработку. Пример кода:

xx <- 1:12
yy <- 1:3
mapply(function(x, y) x / y, xx, yy)
# или
mapply(`/`, xx, yy)

Этот код вернет следующий результат:

 [1]  1.0  1.0  1.0  4.0  2.5  2.0  7.0  4.0  3.0 10.0  5.5  4.0
  1. Использование Map():

Функция Map() также поддерживает переработку векторов. Вы можете сделать это следующим образом:

result <- unlist(Map(`/`, xx, yy))

Результат будет аналогичным:

 [1]  1.0  1.0  1.0  4.0  2.5  2.0  7.0  4.0  3.0 10.0  5.5  4.0
  1. Использование data.frame вместе с map2():

Если вы хотите использовать именно map2(), вы можете создать data.frame, а затем применять map2(), как показано ниже:

result <- data.frame(xx, yy) %>% {map2(.$xx, .$yy, `/`)} %>% unlist()

Этот метод также вернет тот же результат:

 [1]  1.0  1.0  1.0  4.0  2.5  2.0  7.0  4.0  3.0 10.0  5.5  4.0
  1. Прямое деление векторизированных значений:

Если операция, которую вы применяете, является векторизованной, вы можете просто использовать:

xx / yy

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

 [1]  1.0  1.0  1.0  4.0  2.5  2.0  7.0  4.0  3.0 10.0  5.5  4.0
  1. Использование Vectorize():

Если функция, которую вы хотите применить, не поддерживает векторизацию, вы можете создать векторизованную функцию с использованием Vectorize. Это позволит выполнить переработку аргументов:

my_function <- Vectorize(function(x, y) x / y)
result <- my_function(xx, yy)

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

Оцените материал
Добавить комментарий

Капча загружается...