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
purrrtambém nos fornece outra ferramenta interessante para achatar listas: a famíliaflatten(). No fundo,map_chr()é quase um atalho paramap() %>% 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.