Nested loop com o pacote purrr no R

O pacote purrr é um dos pilares do tidyverse, ao lado do dplyr e do operador pipe em termos de utilidade e generalização. Um de seus principais objetivos é facilitar a intenção de fazer um loop com a sintaxe envolvida. Ao invés de ter que escrever um monte de códigos tediosos do tipo "for-loop" - que pouco diz ao leitor sobre o que o loop faz -, a função map do purrr pode ser lida quase como inglês puro e se encaixa perfeitamente em operações encadeadas (pipe).

Mas isso não é tudo que o purrr tem a oferecer. O pacote vai muito além das funcionalidades map, walk e suas variantes, ajudando ainda mais no trabalho com listas. Neste exercício vamos utilizar algumas dessas funcionalidades do purrr para aplicações do tipo nested loop.

Primeiro vamos entender o nested loop com um exemplo mínimo, sem usar o pacote purrr. Vamos supor que você tenha dois vetores numéricos de tamanhos diferentes e que você queira todas as combinações possíveis dos valores de ambos os vetores, concatenando os valores em um único vetor separado por um hífen. Isso poderia ser feito com o controle de fluxo for:


# Nested loop
for (i in 1:2) {
for (j in 1:4) {
print(paste(i, j, sep = "-"))
}
}

## [1] "1-1"
## [1] "1-2"
## [1] "1-3"
## [1] "1-4"
## [1] "2-1"
## [1] "2-2"
## [1] "2-3"
## [1] "2-4"

Com o purrr poderíamos fazer a mesma operação com a função walk neste contexto, onde o .y do loop de dentro é o vetor numérico 1:2 do loop de fora:


library(purrr)

# Nested loop
walk(1:2, ~walk(1:4, ~print(paste(.y, .x, sep = "-")), .y = .x))

## [1] "1-1"
## [1] "1-2"
## [1] "1-3"
## [1] "1-4"
## [1] "2-1"
## [1] "2-2"
## [1] "2-3"
## [1] "2-4"

Uma outra opção seria, em verdade, evitar o nested loop, já que é de leitura dificultosa e requer um trabalho adicional desnecessário. Portanto, seguindo o conselho do pai da linguagem de programação C++, Bjarne Stroustrup:

To become significantly more reliable, code must become more transparent. In particular, nested conditions and loops must be viewed with great suspicion. Complicated control flows confuse programmers. Messy code often hides bugs.

Poríamos criar antes uma combinação de valores usando a função cross2 e então iterar esses elementos em um loop:


library(magrittr)

cross2(1:2, 1:4) %>%
walk(
~print(paste(.[[1]], .[[2]], sep = "-"))
)

## [1] "1-1"
## [1] "2-1"
## [1] "1-2"
## [1] "2-2"
## [1] "1-3"
## [1] "2-3"
## [1] "1-4"
## [1] "2-4"

Muito melhor, concorda?

Agora vamos a um exemplo prático da vida real. Suponha que você esteja trabalhando com os dados desagregados da inflação brasileira, medida pelo IPCA do IBGE e que precise coletar esses dados usando sua API através do pacote sidrar no R. A coleta dos dados pela API tem uma limitação de 50 mil observações por requisição, portanto você precisa criar uma estratégia para coletar esses dados sem ultrapassar esse limite da API.

Uma maneira de fazer isso, não a melhor, é justamente através de um nested loop. Para operacionalizar vamos coletar os dados do IPCA provenientes das tabelas 1419 e 7060 e suas variáveis do SIDRA/IBGE:


library(sidrar)

# Vetor com códigos das tabelas do IPCA
tables <- c("Tabela 1419" = 1419, "Tabela 7060" = 7060)

# Vetor com códigos das variáveis da tabela
variables <- c(
"IPCA - Variacao mensal (%)" = 63,
"IPCA - Peso mensal" = 66,
"IPCA - Variação acumulada no ano (%)" = 69,
"IPCA - Variação acumulada em 12 meses (%)" = 2265
)

# Coletar dados com nested loop
ipca <- tables %>%
map_dfr(
~map_dfr(
.x = variables,
~get_sidra(
x = .y, # vetor de códigos das tabelas (tables)
variable = .x, # vetor de códigos das variáveis (variables)
period = "all"
),
.y = .x
)
)

A outra possibilidade é gerar primeiro uma lista com combinações entre os códigos de tabelas e códigos das variáveis e, então, iterar estes elementos em um único loop:


library(dplyr)

# Coletar dados iterando combinações no loop
ipca2 <- cross2(tables, variables) %>%
map_dfr(
~get_sidra(
x = .[[1]],
variable = .[[2]],
period = "all"
)
)

# Verificar se resultados são equivalentes
all.equal(
arrange(ipca, `Mês`),
arrange(ipca2, `Mês`)
)

## [1] TRUE

Vale enfatizar que eu apenas arranhei a superfície do assunto neste texto, mas espero ter pelo menos instigado você a fazer sua própria investigação sobre o que o purrr pode oferecer, além de tornar as iterações mais legíveis, principalmente para os casos de nested loop.

 

Compartilhe esse artigo

Facebook
Twitter
LinkedIn
WhatsApp
Telegram
Email
Print

Comente o que achou desse artigo

Outros artigos relacionados

Resultado PNADc Trimestral - 3° Trimestre/2024

A Análise Macro apresenta os resultados da PNADc Trimestral do 3º trimestre de 2024, com gráficos elaborados em Python para coleta, tratamento e visualização de dados. Todo o conteúdo, disponível exclusivamente no Clube AM, foi desenvolvido com base nos métodos ensinados nos cursos da Análise Macro, permitindo aos assinantes acesso aos códigos e replicação das análises.

Análise exploratória para modelagem preditiva no Python

Antes de desenvolver bons modelos preditivos é necessário organizar e conhecer muito bem os dados. Neste artigo, damos algumas dicas de recursos, como gráficos, análises e estatísticas, que podem ser usados para melhorar o entendimento sobre os dados usando Python.

Como usar modelos do Sklearn para previsão? Uma introdução ao Skforecast

Prever séries temporais é uma tarefa frequente em diversas áreas, porém exige conhecimento e ferramentas específicas. Os modelos de machine learning do Sklearn são populadores, porém são difíceis de aplicar em estruturas temporais de dados. Neste sentido, introduzimos a biblioteca Skforecast, que integra os modelos do Sklearn e a previsão de séries temporais de forma simples.

Boletim AM

Receba diretamente em seu e-mail gratuitamente nossas promoções especiais e conteúdos exclusivos sobre Análise de Dados!

Boletim AM

Receba diretamente em seu e-mail gratuitamente nossas promoções especiais e conteúdos exclusivos sobre Análise de Dados!

como podemos ajudar?

Preencha os seus dados abaixo e fale conosco no WhatsApp

Boletim AM

Preencha o formulário abaixo para receber nossos boletins semanais diretamente em seu e-mail.