10.2 Iterações intermediárias
Agora que já exploramos os básicos da família map()
podemos partir para
iterações um pouco mais complexas. Observe o laço a seguir:
<- function(x, y) { x + y }
soma_ambos <- 10:15
obj_1 <- 20:25
obj_2 for (i in seq_along(obj_1)) {
<- soma_ambos(obj_1[i], obj_2[i])
obj_1[i]
} obj_1
## [1] 30 32 34 36 38 40
Com a função map2()
podemos reproduzir o laço acima em apenas uma linha. Ela
abstrai a iteração em paralelo, aplica a função em cada par de elementos das
entradas e, assim como sua prima map()
, pode achatar o objeto retornado com os
sufixos _chr
, _dbl
, _int
e _lgl
.
O termo “paralelo” neste capítulos se refere a laços em mais de uma estrutura e não a paralelização de computações em mais de uma unidade de processamento.
<- function(x, y) { x + y }
soma_ambos <- 10:15
obj_1 <- 20:25
obj_2 <- map2_dbl(obj_1, obj_2, soma_ambos)
obj_1 obj_1
## [1] 30 32 34 36 38 40
Como o pacote purrr
é extremamente consistente, a map2()
também funciona com
reticências e fórmulas. Poderíamos, por exemplo, transformar soma_ambos()
em
uma função anônima:
<- 10:15
obj_1 <- 20:25
obj_2 map2_dbl(obj_1, obj_2, ~.x+.y)
## [1] 30 32 34 36 38 40
Desta vez também temos acesso ao placeholder .y
para indicar onde os elementos
de do segundo vetor devem ir.
Para não precisar oferecer uma função para cada número de argumentos, o pacote
purrr
fornece a pmap()
. Para essa função devemos passar uma lista em que cada
elemento é um dos objetos a ser iterado:
<- function(x, y, z) { x + y + z }
soma_varios <- 10:15
obj_1 <- 20:25
obj_2 <- 30:35
obj_3 <- pmap_dbl(list(obj_1, obj_2, obj_3), soma_varios)
obj_1 obj_1
## [1] 60 63 66 69 72 75
Com a pmap()
infelizmente não podemos usar fórmulas. Se quisermos usar uma
função anônima com ela, precisamos declará-la a função no seu corpo:
<- 10:15
obj_1 <- 20:25
obj_2 <- 30:35
obj_3 pmap_dbl(list(obj_1, obj_2, obj_3), function(x, y, z) { x + y + z })
## [1] 60 63 66 69 72 75
A última função que veremos nessa seção é a imap()
. No fundo ela é um
atalho para map2(x, names(x), ...)
quando x
tem nomes e para
map2(x, seq_along(x), ...)
caso contrário:
<- 10:15
obj imap_dbl(obj, ~.x+.y)
## [1] 11 13 15 17 19 21
Como podemos observar, agora .y
é o placeholder para o índice atual (equivalente
ao i
no laço com for
). Naturalmente, assim como toda a família map()
, a
imap()
também funciona com os sufixos de achatamento.