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.


Curso-R