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:
soma_ambos <- function(x, y) { x + y }
obj_1 <- 10:15
obj_2 <- 20:25
for (i in seq_along(obj_1)) {
obj_1[i] <- soma_ambos(obj_1[i], obj_2[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.
soma_ambos <- function(x, y) { x + y }
obj_1 <- 10:15
obj_2 <- 20:25
obj_1 <- map2_dbl(obj_1, obj_2, soma_ambos)
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:
obj_1 <- 10:15
obj_2 <- 20:25
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:
soma_varios <- function(x, y, z) { x + y + z }
obj_1 <- 10:15
obj_2 <- 20:25
obj_3 <- 30:35
obj_1 <- pmap_dbl(list(obj_1, obj_2, obj_3), soma_varios)
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:
obj_1 <- 10:15
obj_2 <- 20:25
obj_3 <- 30:35
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:
obj <- 10:15
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.