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
:
<- function(x) { x + 1 }
soma_um <- 10:15
obj for (i in seq_along(obj)) {
<- soma_um(obj[i])
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.
<- function(x) { x + 1 }
soma_um <- 10:15
obj <- map(obj, soma_um)
obj 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).
<- 10:15
obj 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í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:
<- function(x, n = 1) { x + n }
soma_n <- 10:15
obj 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()
.
<- function(x, n = 1) { x + n }
soma_n <- 10:15
obj 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.