<- c("DBI", "RSQLite", "dbplyr", "arrow")
pacotes install.packages(pacotes)
9 Introdução à Big Data
9.1 Introdução
Neste curso (e na maior parte do curso introdutório), focamos em trabalhar com conjuntos de dados pequenos e que cabem na memória RAM do computador. Isso permite que possamos carregar, manipular e analisar os dados diretamente no R sem grandes preocupações com limitações de hardware.
No entanto, muitas vezes, os dados são grandes demais para caber na memória do computador. Neste caso, é necessário usar técnicas diferentes para trabalhar com esses dados.
O termo Big Data é usado para descrever conjuntos de dados que são tão grandes ou complexos que se tornam difíceis de processar com ferramentas tradicionais.
Big Data é geralmente definido em termos de “3 Vs”: volume, variedade, velocidade.
Nesta aula, vamos utilizar este termo para descrever conjuntos de dados que são grandes demais para caber na memória do computador.
““Big Data” is a relative term depending on who is discussing it. Big Data to Amazon or Google is very different than Big Data to a medium-sized insurance organization, but no less “Big” in the minds of those contending with it.” (A Brief History of Big Data, Keith D, 2017)
Caso não tenha os pacotes necessários instalados, você pode instalar executando o código abaixo:
9.2 Banco de dados SQL
Grande parte dos dados utilizados em pesquisas e análises estão armazenados em bancos de dados relacionais, que utilizam a linguagem SQL (Structured Query Language) para consulta e manipulação de dados.
O objetivo desta aula não é ensinar SQL, mas sim mostrar como podemos usar o R para se conectar a um banco de dados SQL e realizar consultas e manipulações de dados.
O fluxo de trabalho para trabalhar com dados armazenados em bancos de dados SQL no R é semelhante ao que já aprendemos com o uso de data.frames
e tibbles
, mas possui algumas diferenças, como:
Conectar com o banco de dados: em vez de carregar a base completa no R (como fazemos com arquivos
.csv
), precisamos fazer uma conexão com o banco de dados.Pensar no problema que queremos resolver: antes de realizar qualquer consulta, é importante ter em mente o que queremos analisar e quais dados são necessários. Por exemplo: se queremos fazer uma análise dos dados da RAIS em um ano específico, e para um estado específico, não faz sentido carregar todos os dados da RAIS no R. Precisamos pensar em quais operações são necessárias.
Consulta: Fazer as operações necessárias no banco de dados para obter os dados desejados.
Coletar os dados: após realizar a consulta, precisamos “coletar” os dados no R para realizar análises.
Desconectar do banco de dados: após finalizar as análises, é importante desconectar do banco de dados.
Continuar a análise: após coletar os dados, podemos continuar a análise como fizemos anteriormente.
9.2.1 Conexão com bancos de dados SQL
O pacote {DBI}
(R Database Interface) é uma interface para se conectar a bancos de dados SQL. Ele fornece funções que permitem se conectar a diferentes bancos de dados SQL, permitindo que você use a mesma sintaxe.
Para se conectar a um banco de dados específico, você precisa instalar o pacote que fornece a conexão com o banco de dados, como:
PostgreSQL (com o pacote
{RPostgres}
)MySQL ou MariaDB (com o pacote
{RMariaDB}
)SQLite (com o pacote
{RSQLite}
)Google Big Query (com o pacote
{bigrquery}
)odbc (com o pacote
{odbc}
)
# install.packages("DBI")
library(DBI)
O pacote DBI apresenta funções para se conectar a um banco de dados, como dbConnect()
e dbDisconnect()
.
Vamos explorar a função dbConnect()
para conectar a um banco de dados. Essa função recebe como argumento drv
(o driver do banco de dados) e as informações necessárias para a conexão, como: o nome do banco de dados, o usuário, senha, entre outros.
Geralmente, acessamos bancos de dados SQL em um servidor, que requer credenciais de acesso, como usuário e senha.
O código abaixo mostra um exemplo de conexão com um banco de dados PostgreSQL:
<- DBI::dbConnect(
con drv = RPostgres::Postgres(),
host = "...",
user = "...",
port = 5432,
password = "..."
)
No exemplo acima, estamos nos conectando a um banco de dados PostgreSQL, informando o host, usuário, porta e senha. As informações de conexão dependem do banco de dados que você está utilizando, e você deve consultá-las com o administrador do banco de dados.
Perceba que o código acima salva o resultado da conexão no objeto con
. Utilizaremos esse objeto para realizar o acesso ao banco de dados.
Também é possível se conectar a um banco de dados SQLite, que é um banco de dados disponibilizado em um arquivo, e que não requer um servidor:
<- dbConnect(drv = RSQLite::SQLite(),
con # caminho para um arquivo SQLite
dbname = "dados/flights_br.sqlite")
Conseguimos listar as tabelas disponíveis no banco de dados com a função dbListTables()
:
dbListTables(con)
# [1] "voos"
Algo importante a se destacar é que, ao finalizar a análise, é importante desconectar do banco de dados com a função dbDisconnect()
:
dbDisconnect(con)
9.2.2 Exercícios
Em breve!
9.3 Utilizando a sintaxe do dplyr
No curso anterior, aprendemos a usar o pacote {dplyr}
para manipulação de dados. No entanto, exploramos apenas a utilização com o uso de data.frames
e tibbles
.
No entanto, o {dplyr}
possui suporte para diferentes backends que permitem trabalhar com conjuntos de dados que não cabem na memória do computador. Isso significa que podemos usar a mesma sintaxe do {dplyr}
para manipular dados armazenados em bancos de dados SQL, em arquivos Apache Arrow, entre outros. Na documentação, podemos encontrar uma lista de backends disponíveis: dplyr backends.
Vamos explorar dois pacotes que apresentam backends do dplyr: {dbplyr}
(para trabalhar com dados armazenados em bancos de dados sql) e {Arrow}
.
Antes de explorar os pacotes, vamos conhecer duas funções importantes do {dplyr}
que são utilizadas para trabalhar com bancos de dados SQL: tbl()
e collect()
.
tbl()
: cria um objeto que representa uma tabela no banco de dados. Esse objeto é uma referência à tabela, e não carrega os dados na memória.collect()
: coleta os dados da tabela no banco de dados e carrega na memória.
Vamos ver um exemplo de como usar essas funções, a partir de um objeto que representa uma conexão com um banco de dados:
# Carragar o pacote dplyr
library(dplyr)
<- tbl(con, "voos") db_dados_voos
No exemplo acima, criamos um objeto db_dados_voos
que representa a tabela voos
no banco de dados. Perceba que os dados não foram carregados na memória.
Podemos verificar o tipo do objeto criado com a função class()
:
class(db_dados_voos)
# [1] "tbl_SQLiteConnection" "tbl_dbi"
# [3] "tbl_sql" "tbl_lazy"
# [5] "tbl"
Algo muito importante é que, ao usar o tbl()
, não conseguimos visualizar as colunas da tabela com a função names()
, e precisamos usar a função colnames()
:
names(db_dados_voos)
# ! The `names()` method of <tbl_lazy> is for internal
# use only.
# ℹ Did you mean `colnames()`?
# [1] "src" "lazy_query"
Utilizando a função colnames()
, conseguimos visualizar as colunas da tabela:
colnames(db_dados_voos)
# [1] "id_basica"
# [2] "id_empresa"
# [3] "sg_empresa_icao"
# [4] "sg_empresa_iata"
# [5] "nm_empresa"
# [6] "nm_pais"
# ....
Para coletar os dados na memória, utilizamos a função collect()
. Porém o ideal é apenas coletar os dados necessários para a análise, e não a tabela inteira. Vamos explorar exemplos com a função collect()
mais adiante.
9.3.1 Exercícios
Em breve!
9.4 dbplyr
O pacote {dbplyr}
é um backend do {dplyr}
que permite usar a sintaxe do {dplyr}
para manipular dados armazenados em bancos de dados SQL, sem precisar carregar os dados inteiramente na memória.
O que o pacote dbplyr
faz é traduzir as operações do {dplyr}
em consultas SQL, que são executadas diretamente no banco de dados.
Vamos carregar o pacote:
library(dbplyr)
Vamos utilizar o objeto db_dados_voos
que criamos anteriormente para explorar o pacote dbplyr
:
<- tbl(con, "voos") db_dados_voos
As principais funções do dplyr
são suportadas pelo dbplyr
, como filter()
, select()
, mutate()
, group_by()
, summarise()
, entre outras.
Imagine que queremos contar o número de voos por mês e ano. Podemos fazer isso com a função count()
:
<- db_dados_voos |>
voos_contagem_mes count(nr_ano_referencia, nr_mes_referencia)
Perceba que a operação acima não coleta os dados na memória, mas sim traduz a operação em uma consulta SQL que é executada no banco de dados. A função show_query()
permite visualizar a consulta SQL gerada:
show_query(voos_contagem_mes)
# <SQL>
# SELECT `nr_ano_referencia`, `nr_mes_referencia`, COUNT(*) AS `n`
# FROM `voos`
# GROUP BY `nr_ano_referencia`, `nr_mes_referencia`
Algo muito legal de perceber é como muitas funções do {dplyr}
tem nomes muito parecidos com as funções e comandos do SQL. O autor do pacote dplyr
, Hadley Wickham, já utilizava SQL antes de criar o pacote {dplyr}
!
Para coletar os dados na memória, utilizamos a função collect()
. Ao utilizar essa função, o dbplyr
traduz o código em {dplyr}
para uma consulta de banco de dados, que é executada, e então e os dados são coletados na memória.
<- collect(voos_contagem_mes)
df_voos_contagem_mes
df_voos_contagem_mes
# # A tibble: 12 × 3
# nr_ano_referencia nr_mes_referencia n
# <dbl> <dbl> <int>
# 1 2024 1 82196
# 2 2024 2 73587
# 3 2024 3 77415
# 4 2024 4 77478
# 5 2024 5 75139
# 6 2024 6 75319
# 7 2024 7 84388
# 8 2024 8 81439
# 9 2024 9 78120
# 10 2024 10 80455
# 11 2024 11 76429
# 12 2024 12 82044
Nas aulas anteriores, utilizamos os dados de vôos para dezembro/2024. No resultado acima, é possível notar que temos dados de vôos de origem ou destino para o Brasil para todos os meses de 2024.
Perceba que essa base originalmente tem 944 mil linhas, para apenas um ano. Imagine se a gente precisasse trabalhar com toda a série histórica disponível! Dificilmente seria possível utilizando apenas a memória RAM do computador.
Observe também que o objeto df_voos_contagem_mes
é um tibble
:
class(df_voos_contagem_mes)
# [1] "tbl_df" "tbl" "data.frame"
Com os dados coletados na memória, podemos continuar a análise como estamos habituados.
Entretanto, é importante lembrar que nem todas as funções do dplyr
são suportadas pelo dbplyr
.
Um exemplo é a função tail()
, que retorna as últimas linhas de uma tabela:
tail(voos_contagem_mes)
# Error in `tail()`:
# ! `tail()` is not supported on database
# backends.
# Backtrace:
# 1. utils::tail(voos_contagem_mes)
# 2. dbplyr:::tail.tbl_lazy(voos_contagem_mes)
Lembre-se de desconectar do banco de dados após finalizar a análise:
dbDisconnect(con)
9.4.1 Exercícios
Em breve!
9.5 Arrow
Em breve!
9.6 Material complementar
- Capítulos do livro “R para Ciência de Dados” (2 ed) por Hadley Wickham, Mine Çetinkaya-Rundel, e Garrett Grolemund: