EAE1106 - Métodos Computacionais para Economia
Faculdade de
Economia, Administração, Contabilidade e Atuária
Universidade de São
Paulo
Prof. Arthur Viaro
1º semestre de 2026
O Tidyverse é uma coleção de pacotes do R projetados para trabalhar juntos. Eles compartilham uma mesma lógica: funções simples, com nomes em inglês claro, que fazem uma coisa só e se encadeiam bem.
Os pacotes que usaremos nesta aula:
| Pacote | Para quê serve |
|---|---|
dplyr |
Filtrar, ordenar, agrupar, resumir |
tidyr |
Reformatar tabelas (largo ↔︎ longo) |
readr |
Importar arquivos CSV |
tibble |
Tabelas modernas |
Analogia com Python/pandas: O Tidyverse em R é, em muitos aspectos, o equivalente ao ecossistema pandas + numpy + matplotlib em Python, mas com uma filosofia mais integrada e consistente.
Um tibble é simplesmente um data.frame
melhorado. Ele não faz conversões silenciosas e mostra as dimensões e os
tipos de cada coluna automaticamente.
# Criando um tibble manualmente
dados_america_sul <- tibble(
pais = c("Brasil", "Argentina", "Chile", "Colômbia", "Peru"),
pib = c(2.08, 0.63, 0.32, 0.34, 0.24), # trilhões de USD
populacao = c(215, 46, 19, 51, 33), # milhões
inflacao = c(4.6, 142.7, 12.8, 11.7, 6.3), # % ao ano
gini = c(48.9, 42.3, 44.4, 55.9, 40.2)
)
dados_america_sul## Rows: 5
## Columns: 5
## $ pais <chr> "Brasil", "Argentina", "Chile", "Colômbia", "Peru"
## $ pib <dbl> 2.08, 0.63, 0.32, 0.34, 0.24
## $ populacao <dbl> 215, 46, 19, 51, 33
## $ inflacao <dbl> 4.6, 142.7, 12.8, 11.7, 6.3
## $ gini <dbl> 48.9, 42.3, 44.4, 55.9, 40.2
|>O operador pipe (|>) é a peça central do Tidyverse,
pois permite executar operações em sequência.
Basicamente, ele passa o resultado da expressão anterior como primeiro argumento da próxima função.
Sem pipe é difícil de ler de dentro para fora:
## [1] 3.67
Com pipe, lê-se da esquerda para a direita, como uma receita:
## [1] 3.67
Atalho no RStudio:
Ctrl + Shift + M(configure para usar|>nativo em Tools → Global Options → Code)
Nota histórica: O pipe
|>foi introduzido no R 4.1. Em códigos mais antigos você verá%>%do pacotemagrittr. Os dois se comportam de forma idêntica na maioria dos casos.
dplyr - As Seis Funções EssenciaisO dplyr tem seis funções principais. Cada uma responde a
uma pergunta diferente sobre seus dados:
| Pergunta | Função |
|---|---|
| Quais linhas me interessam? | filter() |
| Em que ordem quero ver? | arrange() |
| Quais colunas preciso? | select() |
| Quero calcular algo novo? | mutate() |
| Quero um resumo dos dados? | summarize() |
| Quero o resumo por grupo? | group_by() |
Vamos usar o dataset nycflights13 — 336.776 voos
partindo de Nova York em 2013:
## Rows: 336,776
## Columns: 19
## $ year <int> 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2…
## $ month <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
## $ day <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
## $ dep_time <int> 517, 533, 542, 544, 554, 554, 555, 557, 557, 558, 558, …
## $ sched_dep_time <int> 515, 529, 540, 545, 600, 558, 600, 600, 600, 600, 600, …
## $ dep_delay <dbl> 2, 4, 2, -1, -6, -4, -5, -3, -3, -2, -2, -2, -2, -2, -1…
## $ arr_time <int> 830, 850, 923, 1004, 812, 740, 913, 709, 838, 753, 849,…
## $ sched_arr_time <int> 819, 830, 850, 1022, 837, 728, 854, 723, 846, 745, 851,…
## $ arr_delay <dbl> 11, 20, 33, -18, -25, 12, 19, -14, -8, 8, -2, -3, 7, -1…
## $ carrier <chr> "UA", "UA", "AA", "B6", "DL", "UA", "B6", "EV", "B6", "…
## $ flight <int> 1545, 1714, 1141, 725, 461, 1696, 507, 5708, 79, 301, 4…
## $ tailnum <chr> "N14228", "N24211", "N619AA", "N804JB", "N668DN", "N394…
## $ origin <chr> "EWR", "LGA", "JFK", "JFK", "LGA", "EWR", "EWR", "LGA",…
## $ dest <chr> "IAH", "IAH", "MIA", "BQN", "ATL", "ORD", "FLL", "IAD",…
## $ air_time <dbl> 227, 227, 160, 183, 116, 150, 158, 53, 140, 138, 149, 1…
## $ distance <dbl> 1400, 1416, 1089, 1576, 762, 719, 1065, 229, 944, 733, …
## $ hour <dbl> 5, 5, 5, 5, 6, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 6, 6…
## $ minute <dbl> 15, 29, 40, 45, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0…
## $ time_hour <dttm> 2013-01-01 05:00:00, 2013-01-01 05:00:00, 2013-01-01 0…
filter() — Escolhendo Linhasfilter() mantém apenas as linhas que satisfazem uma
condição lógica.
# Identificar voos cancelados (sem horário de partida registrado)
flights |> filter(is.na(dep_time))Comparação com Python/pandas:
arrange() — Ordenando LinhasPodemos reorganizar as linhas de acordo com uma ou mais variáveis.
select() — Escolhendo ColunasMuitas vezes a base possui dezenas de colunas, mas precisamos trabalhar apenas com algumas delas.
# Funções auxiliares muito úteis
flights |> select(starts_with("dep")) # colunas que começam com "dep"mutate() — Criando Novas Colunasmutate() adiciona colunas calculadas a partir das
existentes.
flights |>
mutate(
ganho_tempo = dep_delay - arr_delay, # tempo recuperado no ar
velocidade = distance / air_time * 60 # milhas por hora
) |>
select(flight, ganho_tempo, velocidade)# case_when() — condicional "elegante" para criar categorias
flights |>
mutate(
categoria = case_when(
dep_delay < 0 ~ "Adiantado",
dep_delay == 0 ~ "No horário",
dep_delay <= 15 ~ "Atraso leve",
dep_delay <= 60 ~ "Atraso moderado",
TRUE ~ "Atraso grave"
)
) |>
count(categoria)summarize() e group_by() — Resumindo
Dadossummarize() colapsa a tabela em uma única linha de
estatísticas resumidas.
Por que
na.rm = TRUE? Algumas funções comomean()emax()retornamNAse houver qualquer valor faltante nos dados. O argumentona.rm = TRUEdiz: “ignore os NAs e calcule com o restante”.
flights |>
summarize(
n_voos = n(),
atraso_med = mean(dep_delay, na.rm = TRUE),
atraso_max = max(dep_delay, na.rm = TRUE)
)A combinação group_by() +
summarize() é a mais poderosa do dplyr. Ela
calcula o resumo separadamente para cada grupo:
# Atraso médio por mês
flights |>
group_by(month) |>
summarize(
n_voos = n(),
atraso_medio = mean(dep_delay, na.rm = TRUE),
pct_atrasado = mean(dep_delay > 0, na.rm = TRUE) * 100,
.groups = "drop" # Remove agrupamento após summarize
)Quando a informação está em tabelas diferentes, usamos joins para combiná-las por uma chave comum.
Os tipos de join mais usados são:
| Função | O que faz |
|---|---|
left_join() |
Mantém todas as linhas da tabela da esquerda |
right_join() |
Mantém todas as linhas da tabela da direita |
inner_join() |
Mantém só as linhas com correspondência em ambas |
full_join() |
Mantém todas as linhas de ambas as tabelas |
anti_join() |
Mantém linhas da esquerda sem correspondência |
# Adicionar o nome completo da companhia aérea à tabela de voos
flights |>
left_join(airlines, by = "carrier") |>
select(carrier, name, dep_delay, arr_delay) |>
head()# Quais destinos têm maior atraso médio?
flights |>
group_by(dest) |>
summarize(atraso = mean(arr_delay, na.rm = TRUE), n = n()) |>
filter(n > 100) |>
left_join(airports, by = c("dest" = "faa")) |>
select(dest, name, atraso, n) |>
arrange(desc(atraso))Um conjunto de dados está no formato tidy quando:
Dados no formato largo são comuns em planilhas, mas difíceis de analisar. Dados no formato longo (tidy) são o que o R espera.
# Formato LARGO — cada ano é uma coluna (não tidy)
tabela_wide <- tibble(
pais = c("Brasil", "Argentina", "Chile"),
pib_2020 = c(1.44, 0.39, 0.25),
pib_2021 = c(1.61, 0.49, 0.32),
pib_2022 = c(1.92, 0.63, 0.30)
)
tabela_wide# read_csv() usa vírgula como separador e ponto como decimal (padrão internacional)
dados <- read_csv("dados.csv")
# read_csv2() usa ponto-e-vírgula como separador e vírgula como decimal
dados_br <- read_csv2("dados_brasil.csv")
# Opções úteis
dados <- read_csv(
"dados.csv",
na = c("", "NA", "N/A", "-"), # o que tratar como NA
skip = 2 # pular linhas de cabeçalho
)
# Exportar
write_csv(dados, "resultado.csv")Vamos usar a Penn World Table (PWT 10.01), uma das bases de dados mais usadas em macroeconomia comparada, para investigar a relação entre investimento e crescimento do PIB per capita ao longo do tempo.
A Penn World Table fornece dados comparáveis internacionalmente sobre PIB, produtividade, horas trabalhadas, capital físico e muito mais, cobrindo mais de 180 países desde 1950.
# O pacote pwt10 fornece acesso direto à Penn World Table 10.01
# install.packages("pwt10")
library(pwt10)
# Carregar a base
data("pwt10.01")
# Visão geral
glimpse(pwt10.01)## Rows: 12,810
## Columns: 52
## $ country <fct> "Aruba", "Aruba", "Aruba", "Aruba", "Aruba", "Aruba", "Aruba…
## $ isocode <fct> ABW, ABW, ABW, ABW, ABW, ABW, ABW, ABW, ABW, ABW, ABW, ABW, …
## $ year <int> 1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959, …
## $ currency <fct> Aruban Guilder, Aruban Guilder, Aruban Guilder, Aruban Guild…
## $ rgdpe <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ rgdpo <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ pop <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ emp <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ avh <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ hc <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ ccon <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ cda <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ cgdpe <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ cgdpo <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ cn <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ ck <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ ctfp <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ cwtfp <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ rgdpna <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ rconna <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ rdana <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ rnna <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ rkna <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ rtfpna <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ rwtfpna <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ labsh <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ irr <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ delta <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ xr <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ pl_con <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ pl_da <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ pl_gdpo <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ i_cig <fct> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ i_xm <fct> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ i_xr <fct> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ i_outlier <fct> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ i_irr <fct> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ cor_exp <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ statcap <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ csh_c <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ csh_i <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ csh_g <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ csh_x <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ csh_m <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ csh_r <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ pl_c <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ pl_i <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ pl_g <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ pl_x <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ pl_m <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ pl_n <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ pl_k <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
# Selecionar as variáveis de interesse e renomear para facilitar
pwt <- pwt10.01 |>
select(
pais = country,
iso = isocode,
ano = year,
rgdpna, # PIB real (milhões USD PPP, base 2017)
pop, # população (milhões)
emp, # pessoas empregadas (milhões)
ck, # estoque de capital (milhões USD PPP)
csh_i, # participação do investimento no PIB (fração)
avh # horas médias trabalhadas por ano
) |>
mutate(
pib_pc = rgdpna / pop * 1000 # PIB per capita em USD PPP
)
glimpse(pwt)## Rows: 12,810
## Columns: 10
## $ pais <fct> "Aruba", "Aruba", "Aruba", "Aruba", "Aruba", "Aruba", "Aruba", …
## $ iso <fct> ABW, ABW, ABW, ABW, ABW, ABW, ABW, ABW, ABW, ABW, ABW, ABW, ABW…
## $ ano <int> 1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959, 196…
## $ rgdpna <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ pop <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ emp <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ ck <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ csh_i <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ avh <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ pib_pc <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
# Quantos países e anos temos?
pwt |>
summarize(
n_paises = n_distinct(iso),
ano_min = min(ano),
ano_max = max(ano),
n_obs = n()
)Os países que mais investiram (como % do PIB) entre 1960 e 2019 cresceram mais?
Esta é uma das questões centrais da teoria do crescimento econômico (Solow, 1956). Vamos explorar os dados.
# Focar no período 1960–2019, excluindo países com dados insuficientes
crescimento_pais <- pwt |>
filter(ano >= 1960, ano <= 2019) |>
filter(!is.na(pib_pc), !is.na(csh_i)) |>
group_by(pais, iso) |>
# Manter apenas países com pelo menos 40 anos de dados
filter(n() >= 40) |>
summarize(
pib_pc_1960 = first(pib_pc[ano == min(ano)]),
pib_pc_2019 = last(pib_pc[ano == max(ano)]),
inv_medio = mean(csh_i, na.rm = TRUE) * 100, # em %
anos_obs = n(),
.groups = "drop"
) |>
filter(!is.na(pib_pc_1960), !is.na(pib_pc_2019), pib_pc_1960 > 0) |>
mutate(
# Taxa de crescimento anualizada do PIB per capita
crescimento_anual = (pib_pc_2019 / pib_pc_1960)^(1 / 59) - 1,
crescimento_anual = crescimento_anual * 100, # em %
# Categorizar países por nível de investimento
quartil_inv = ntile(inv_medio, 4),
grupo_inv = case_when(
quartil_inv == 1 ~ "Baixo (Q1)",
quartil_inv == 2 ~ "Médio-baixo (Q2)",
quartil_inv == 3 ~ "Médio-alto (Q3)",
quartil_inv == 4 ~ "Alto (Q4)"
),
grupo_inv = factor(grupo_inv, levels = c(
"Baixo (Q1)", "Médio-baixo (Q2)",
"Médio-alto (Q3)", "Alto (Q4)"
))
)
crescimento_pais# Crescimento médio por quartil de investimento
crescimento_pais |>
group_by(grupo_inv) |>
summarize(
n_paises = n(),
inv_medio_pct = mean(inv_medio),
crescimento_medio = mean(crescimento_anual),
crescimento_med = median(crescimento_anual)
) |>
arrange(grupo_inv)# Os 10 países que mais cresceram
crescimento_pais |>
slice_max(crescimento_anual, n = 10) |>
select(pais, iso, inv_medio, crescimento_anual) |>
mutate(across(where(is.numeric), \(x) round(x, 2)))# Os 10 países com menor crescimento
crescimento_pais |>
slice_min(crescimento_anual, n = 10) |>
select(pais, iso, inv_medio, crescimento_anual) |>
mutate(across(where(is.numeric), \(x) round(x, 2)))# Correlação entre investimento e crescimento
cor_inv_cresc <- cor(
crescimento_pais$inv_medio,
crescimento_pais$crescimento_anual,
use = "complete.obs"
)
cat("Correlação entre taxa de investimento e crescimento:", round(cor_inv_cresc, 3))## Correlação entre taxa de investimento e crescimento: 0.217
# Onde o Brasil se posiciona?
crescimento_pais |>
filter(iso == "BRA") |>
select(pais, inv_medio, crescimento_anual, grupo_inv) |>
mutate(across(where(is.numeric), \(x) round(x, 2)))1. Use o dataset flights para encontrar
todos os voos que: - Chegaram com mais de 2 horas de atraso, mas saíram
no horário - Foram operados pela United (UA), American
(AA) ou Delta (DL) - Partiram no verão
americano (julho, agosto ou setembro)
2. Para cada mês de 2013, calcule: número de voos, atraso médio de chegada, percentual de voos cancelados. Qual foi o pior mês?
3. Qual aeroporto de origem (EWR,
JFK ou LGA) tem o maior atraso médio? Esse
resultado é consistente para todas as companhias aéreas?
4. Usando pivot_wider(), crie uma
tabela que mostre o atraso médio de chegada por companhia aérea (linhas)
e mês (colunas).
5. (Desafio — Penn World Table) A análise
acima usou a taxa de investimento como porcentagem do PIB. Refaça a
análise usando o estoque de capital por trabalhador
(ck / emp) como variável principal. A relação com o
crescimento é mais forte ou mais fraca? O que isso sugere
teoricamente?
Material baseado em: Wickham, H., Çetinkaya-Rundel, M. & Grolemund, G. (2023). R for Data Science (2ª ed.). O’Reilly. Disponível em: https://r4ds.hadley.nz/