10.1 Iterações básicas

A primeira família de funções do purrr que veremos também é a mais útil e extensível. As funções map() são quase como substitutas para laços for, elas abstraem a iteração em apenas uma linha. Veja esse exemplo de laço usando for:

soma_um <- function(x) { x + 1 }
obj <- 10:15
for (i in seq_along(obj)) {
  obj[i] <- soma_um(obj[i])
}
obj
## [1] 11 12 13 14 15 16

O que de fato estamos tentando fazer com o laço acima? Temos um vetor (obj) e queremos aplicar uma função (soma_um()) em cada elemento dele. A função map() remove a necessidade de declaramos um objeto iterador auxiliar (i) e simplesmente aplica a função desejada em cada elemento do objeto dado.

soma_um <- function(x) { x + 1 }
obj <- 10:15
obj <- map(obj, soma_um)
obj
## [[1]]
## [1] 11
## 
## [[2]]
## [1] 12
## 
## [[3]]
## [1] 13
## 
## [[4]]
## [1] 14
## 
## [[5]]
## [1] 15
## 
## [[6]]
## [1] 16

Como você deve ter percebido, o resultado da execução acima não é exatamente igual ao que tivemos com o laço. Isso acontece porque a map() tenta ser extremamente genérica, retornando por padrão uma lista com um elemento para cada saída.

Se quisermos “achatar” o resultado, devemos informar qual será o seu tipo. Isso é super simples e pode ser feito com as irmãs da map(): map_chr() (para strings), map_dbl() (para números reais), map_int() (para números inteiros) e map_lgl() (para booleanos).

obj <- 10:15
map_dbl(obj, soma_um)
## [1] 11 12 13 14 15 16

O purrr também nos fornece outra ferramenta interessante para achatar listas: a família flatten(). No fundo, map_chr() é quase um atalho para map() %>% flatten_chr()!

Algo bastante útil da família map() é a possibilidade de passar argumentos fixos para a função que será aplicada. A primeira forma de fazer isso envolve fórmulas:

soma_n <- function(x, n = 1) { x + n }
obj <- 10:15
map_dbl(obj, ~soma_n(.x, 2))
## [1] 12 13 14 15 16 17

Como vemos no exemplo acima, para utilizar fórmulas precisamos colocar um til (~) antes da função que será chamada. Feito isso, podemos utilizar o placeholder .x para indicar onde deve ser colocado cada elemento de obj.

A outra forma de passar argumentos para a função é através das reticências da map(). Desta maneira precisamos apenas dar o nome do argumento e seu valor logo após a função soma_n().

soma_n <- function(x, n = 1) { x + n }
obj <- 10:15
map_dbl(obj, soma_n, n = 2)
## [1] 12 13 14 15 16 17

Usando fórmulas temos uma maior flexibilidade (podemos, por exemplo, declarar funções anônimas como ~.x+2), enquanto com as reticências temos maior legibilidade.


Curso-R