Вопрос или проблема
Я пытаюсь запустить следующий код:
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()
не выполняет автоматическую переработку более короткого вектора. Однако существуют другие методы, которые могут помочь вам достичь желаемого результата.
- Использование
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
- Использование
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
- Использование
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
- Прямое деление векторизированных значений:
Если операция, которую вы применяете, является векторизованной, вы можете просто использовать:
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()
:
Если функция, которую вы хотите применить, не поддерживает векторизацию, вы можете создать векторизованную функцию с использованием Vectorize
. Это позволит выполнить переработку аргументов:
my_function <- Vectorize(function(x, y) x / y)
result <- my_function(xx, yy)
В итоге, вы имеет множество подходов, каждый из которых можно использовать в зависимости от ваших предпочтений и требований к коду.