Boas-vindas a mais um curso na Alura, onde vamos trabalhar com a biblioteca Polars, voltada para a manipulação de dados em larga escala! Meu nome é Allan Spadini, sou instrutor na escola de Dados da Alura, e irei te acompanhar ao longo dessa jornada de aprendizado.
Audiodescrição: Allan se descreve como um homem branco, com cabelo curto liso castanho-escuro, e olhos castanho-escuros. Ele veste uma camisa preta e está no estúdio da Alura, com uma parede clara ao fundo iluminada em gradiente verde e azul, uma planta à direita, e uma estante preta à esquerda contendo enfeites, plantas e pontos de iluminação amarela.
Iremos lidar com tabelas e dataframes muito grandes, que necessitarão do uso da Polars, uma das bibliotecas mais rápidas e otimizadas da linguagem Python.
Além disso, trabalharemos com a biblioteca para realizar operações avançadas em processamento de dados, especialmente em grandes datasets. Essas operações incluirão desde o pivoteamento dos dados até o salvamento em formatos comuns de big data, como o .parquet
.
Também abordaremos o particionamento dos dados, utilizando o conhecimento que iremos adquirir sobre o dataset ao longo do processamento.
Esperamos que você nos acompanhe nos próximos vídeos, para darmos início aos estudos e começarmos a explorar a biblioteca. Nos encontramos na sequência!
Trabalhamos como cientistas de dados em um grande grupo de varejo e recebemos a tarefa de analisar um extenso conjunto de dados relacionado a esse grupo. Devido ao tamanho do dataset, precisaremos lidar com esse desafio.
Para isso, utilizaremos a biblioteca Polars, que nos permitirá analisar esse dataset de forma semelhante à biblioteca Pandas, mas de maneira mais eficiente.
A biblioteca Polars é escrita em Rust e oferece diversas facilidades.
O primeiro desafio será localizar o dataset. Neste caso, subimos a pasta do dataset para o Google Drive, então vamos acessá-lo nessa plataforma.
No menu lateral esquerdo do Google Drive, vamos acessar "Arquivos" e conectar ao Drive. Após a conexão, que pode demorar alguns instantes, a pasta do Google Drive aparecerá, permitindo que o arquivo seja encontrado dentro dela.
No nosso caso, o arquivo está localizado em "MyDrive > Alura > Cursos > 4003 - Polars: manipulando tabelas". Precisamos do arquivo dadocurso.zip
, então clicaremos em ⁝
ao lado do nome do arquivo e selecionaremos "Copiar caminho".
Feito isso, basta colar em uma nova célula no notebook:
'/content/drive/MyDrive/Alura/Cursos/4403 - Polars: manipulando tabelas/Projeto/dadocurso.zip'
Há uma pequena diferença entre Polars e Pandas: a Polars não possui a funcionalidade de ler arquivos .zip
. Portanto, abriremos com outra biblioteca.
Na primeira célula, o caminho será atribuído à variável url
:
# url = '/content/drive/MyDrive/Alura/Cursos/4403 - Polars: manipulando tabelas/Projeto/dadocurso.zip'
zipfile
Após executar, utilizaremos a biblioteca zipfile
. Para isso, faremos o import
de zipfile
em uma nova célula. Feito isso, basta executar com "Shift + Enter".
import zipfile
Agora, faremos a leitura do arquivo. Para ler o arquivo com a biblioteca zipfile
, utilizaremos o comando with zipfile.ZipFile()
em uma nova célula. Em seguida, entre parênteses, passaremos url
. Entre aspas duplas, passaremos o comando r
. Por fim, definiremos as zip_ref
.
with zipfile.ZipFile(url, 'r') as zip_ref:
O objetivo é extrair todos os arquivos. Para isso, utilizaremos o termo extract_path
. O extract_path
é exatamente igual à variável url
.
Em uma nova célula, abaixo da importação de zipfile
, vamos chamar extract_patch
e definir como o caminho do arquivo dadocurso.zip
. Assim, todos os arquivos da pasta compactada serão extraídos para a pasta "Projeto".
extract_path = '/content/drive/MyDrive/Alura/Cursos/4403 - Polars: manipulando tabelas/Projeto/'
Feito isso, vamos adicionar o comando zip_ref.extractall(extract_path)
ao escopo de zip_ref
. Ao executá-lo, ele deverá ser executado adequadamente. O processo pode demorar um pouco, mas, após a execução, o arquivo estará na pasta.
with zipfile.ZipFile(url, 'r') as zip_ref:
zip_ref.extractall(extract_path)
Em seguida, utilizaremos a biblioteca Polars para fazer a leitura do arquivo, muito semelhante à biblioteca Pandas, pois vamos ler um arquivo CSV. Para começar, faremos o import
de polars
:
import polars as pl
caminho_csv
Após executar este comando, precisaremos do caminho do arquivo CSV, que está dentro da pasta "Projeto". Basta substituir a extensão .zip
por .csv
.
Vamos copiar e colar o caminho do arquivo em uma nova célula. Ele será armazenado em caminho_csv
como dadocurso.csv
. Novamente, executamos com "Shift + Enter".
caminho_csv = '/content/drive/MyDrive/Alura/Cursos/4403 - Polars: manipulando tabelas/Projeto/dadocurso.csv'
Agora, queremos usar o método read_csv()
. No nosso caso, colocaremos no dataframe df
, utilizando o comando df = pl.read_csv(caminho_csv)
.
O arquivo
caminho_csv
não possui formatação específica.
df = pl.read_csv(caminho_csv)
Um detalhe importante é que faremos uma cópia desse arquivo, usando o comando df_original = df.clone()
na mesma célula, para podermos aproveitar o dataframe original em relação a alguma mudança que desejarmos fazer no arquivo.
df = pl.read_csv(caminho_csv)
df_original = df.clone()
Para finalizar, vamos visualizar as primeiras linhas do arquivo, utilizando o comando df.head()
em uma nova célula. Após executar, temos o seguinte resultado:
df.head()
Visualização dos cinco primeiros registros da tabela.
Região | País | Tipo de Item | Canal de Venda | Prioridade do Pedido | Data do Pedido | ID do Pedido | Data de Envio | Unidades Vendidas | Preço Unitário | Custo Unitário | Receita Total | Custo Total | Lucro Total |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
str | str | str | str | str | str | i64 | str | i64 | f64 | f64 | f64 | f64 | f64 |
"Australia and Oceania" | "Palau" | "Office Supplies" | "Online" | "H" | "3/6/2016" | 517073523 | "3/26/2016" | 2401 | 651.21 | 524.96 | 1.2508e6 | 1.2604e6 | -9584.792 |
"Europe" | "Poland" | "Beverages" | "Online" | "L" | "4/18/2010" | 380507028 | "5/26/2010" | 9340 | 47.45 | 31.79 | 354546.4 | 296918.6 | 57627.8 |
"North America" | "Canada" | "Cereal" | "Online" | "M" | "1/8/2015" | 504055583 | "1/31/2015" | 103 | 205.7 | 117.11 | 16949.68 | 12062.33 | 4887.35 |
"Europe" | "Belarus" | "Snacks" | "Online" | "C" | "1/19/2014" | 954955518 | "2/27/2014" | 1414 | 152.58 | 97.44 | 172598.496 | 137780.16 | 34818.336 |
"Middle East and North Africa" | "Oman" | "Cereal" | "Offline" | "H" | "4/26/2019" | 970755660 | "6/2/2019" | 7027 | 205.7 | 117.11 | 1.1564e6 | 822931.97 | 333431.15 |
Como resultado, encontraremos diversas colunas no arquivo, incluindo o nome do país, com informações sobre produtos e compras de diferentes clientes no site.
Há colunas de custo total, lucro total, receita total, entre outras. Com isso, já temos uma ideia da estrutura do arquivo e podemos começar a exploração dos dados.
No próximo vídeo, faremos uma análise para verificar se há algo que impeça a análise exploratória dos dados, como dados nulos, entre outros. Nos encontramos na sequência!
Anteriormente, realizamos o carregamento dos dados e obtivemos uma ideia geral de como está o dataset, identificando o tipo de problema com o qual lidamos, que é de uma empresa do setor de varejo. Agora, queremos verificar a qualidade dos nossos dados para garantir que estejam adequados para análise. Primeiramente, queremos observar os tipos de dados e verificar a presença de dados nulos ou do tipo NaN, que podem exigir processamento adicional.
Nesse momento, já temos algumas informações iniciais.
Quando utilizamos o comando df.head()
com a biblioteca Polars, algumas informações foram exibidas, como se o dado é do tipo string (str
) ou do tipo inteiro (i64
), por exemplo.
df.head()
Visualização dos cinco primeiros registros da tabela.
Região | País | Tipo de Item | Canal de Venda | Prioridade do Pedido | Data do Pedido | ID do Pedido | Data de Envio | Unidades Vendidas | Preço Unitário | Custo Unitário | Receita Total | Custo Total | Lucro Total |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
str | str | str | str | str | str | i64 | str | i64 | f64 | f64 | f64 | f64 | f64 |
"Australia and Oceania" | "Palau" | "Office Supplies" | "Online" | "H" | "3/6/2016" | 517073523 | "3/26/2016" | 2401 | 651.21 | 524.96 | 1.2508e6 | 1.2604e6 | -9584.792 |
"Europe" | "Poland" | "Beverages" | "Online" | "L" | "4/18/2010" | 380507028 | "5/26/2010" | 9340 | 47.45 | 31.79 | 354546.4 | 296918.6 | 57627.8 |
"North America" | "Canada" | "Cereal" | "Online" | "M" | "1/8/2015" | 504055583 | "1/31/2015" | 103 | 205.7 | 117.11 | 16949.68 | 12062.33 | 4887.35 |
"Europe" | "Belarus" | "Snacks" | "Online" | "C" | "1/19/2014" | 954955518 | "2/27/2014" | 1414 | 152.58 | 97.44 | 172598.496 | 137780.16 | 34818.336 |
"Middle East and North Africa" | "Oman" | "Cereal" | "Offline" | "H" | "4/26/2019" | 970755660 | "6/2/2019" | 7027 | 205.7 | 117.11 | 1.1564e6 | 822931.97 | 333431.15 |
A biblioteca interpreta nossos dados e verifica se estão na forma adequada, como uma data sendo entendida como string ou um número sendo compreendido como inteiro.
dtypes
No entanto, queremos verificar isso com mais detalhes.
Se houver muitas colunas, talvez não seja possível visualizar todas as informações. Nesse caso, podemos usar df.dtypes
para visualizar as informações de maneira mais detalhada, permitindo identificar quantas strings, números inteiros e floats temos nos dados.
df.dtypes
Retorno do comando:
[String,
String,
String,
String,
String,
String,
Int64,
String,
Int64,
Float64,
Float64,
Float64,
Float64,
Float64]
describe()
Outra abordagem é realizar o df.describe()
, que proporciona uma visão geral dos dados e de variáveis específicas que podem ser de interesse para a análise.
df.describe()
statistic | Região | País | Tipo de Item | Canal de Venda | Prioridade do Pedido | Data do Pedido | ID do Pedido | Data de Envio | Unidades Vendidas | Preço Unitário | Custo Unitário | Receita Total | Custo Total | Lucro Total |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
str | str | str | str | str | str | str | f64 | str | f64 | f64 | f64 | f64 | f64 | f64 |
"count" | "5000000" | "5000000" | "5000000" | "5000000" | "5000000" | "5000000" | 5e6 | "5000000" | 5e6 | 5e6 | 5e6 | 5e6 | 5e6 | 5e6 |
"null_count" | "0" | "0" | "0" | "0" | "0" | "0" | 0.0 | "0" | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
"mean" | null | null | null | null | null | null | 5.4989e8 | null | 4999.991061 | 266.190616 | 187.655991 | 1.1439e6 | 938378.122412 | 205508.425247 |
"std" | null | null | null | null | null | null | 2.5978e8 | null | 2886.787007 | 217.015273 | 175.701379 | 1.3158e6 | 1.1501e6 | 451094.254368 |
"min" | "Asia" | "Afghanistan" | "Baby Food" | "Offline" | "C" | "1/1/2010" | 1.00000321e8 | "1/1/2010" | 1.0 | 9.33 | 6.92 | 7.464 | 6.92 | -271780.0 |
"25%" | null | null | null | null | null | null | 3.24965131e8 | null | 2500.0 | 109.28 | 56.67 | 231366.2 | 161925.12 | 5065.57 |
"50%" | null | null | null | null | null | null | 5.49764287e8 | null | 4999.0 | 205.7 | 117.11 | 658009.728 | 467712.0 | 80190.0 |
"75%" | null | null | null | null | null | null | 7.74837243e8 | null | 7500.0 | 437.2 | 364.69 | 1.5568e6 | 1.1974e6 | 258412.7 |
"max" | "Sub-Saharan Africa" | "Zimbabwe" | "Vegetables" | "Online" | "M" | "9/9/2020" | 9.99999892e8 | "9/9/2020" | 10000.0 | 668.27 | 524.96 | 1.002405e7 | 5.2496e6 | 4.99865e6 |
Variáveis com valores do tipo float (f64
), como "Preço Unitário", são importantes, pois ao realizar o df.describe()
, obtemos estatísticas descritivas.
Nessas estatísticas, podemos visualizar valores como a média, acessando a média do preço unitário praticado ou do custo unitário, entre outras informações.
Podemos também selecionar apenas os valores inteiros e do tipo float, uma vez que tentamos realizar cálculos que não fazem sentido com strings. Exibir a média de valores de texto resulta em um valor nulo (null
), que não é esteticamente agradável na tela. Para selecionar apenas as informações inteiras e do tipo float, utilizamos o método df.select()
.
Com esse método, faremos uma seleção dos dados, passando as colunas de interesse como parâmetro entre parênteses. Utilizaremos pl.col()
, especificando pl.Int64
e pl.Float64
para pegar apenas as informações desses tipos.
Por fim, adicionamos o método describe()
para exibir o mesmo tipo de informação, mas agora de forma mais delimitada, focando apenas nas informações de interesse.
df.select(pl.col(pl.Int64, pl.Float64)).describe()
statistic | ID do Pedido | Unidades Vendidas | Preço Unitário | Custo Unitário | Receita Total | Custo Total | Lucro Total |
---|---|---|---|---|---|---|---|
str | f64 | f64 | f64 | f64 | f64 | f64 | f64 |
"count" | 5e6 | 5e6 | 5e6 | 5e6 | 5e6 | 5e6 | 5e6 |
"null_count" | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
"mean" | 5.4989e8 | 4999.991061 | 266.190616 | 187.655991 | 1.1439e6 | 938378.122412 | 205508.425247 |
"std" | 2.5978e8 | 2886.787007 | 217.015273 | 175.701379 | 1.3158e6 | 1.1501e6 | 451094.254368 |
"min" | 1.00000321e8 | 1.0 | 9.33 | 6.92 | 7.464 | 6.92 | -271780.0 |
"25%" | 3.24965131e8 | 2500.0 | 109.28 | 56.67 | 231366.2 | 161925.12 | 5065.57 |
"50%" | 5.49764287e8 | 4999.0 | 205.7 | 117.11 | 658009.728 | 467712.0 | 80190.0 |
"75%" | 7.74837243e8 | 7500.0 | 437.2 | 364.69 | 1.5568e6 | 1.1974e6 | 258412.7 |
"max" | 9.99999892e8 | 10000.0 | 668.27 | 524.96 | 1.002405e7 | 5.2496e6 | 4.99865e6 |
Observação: nesse caso, lidamos com um dataset grande e usamos a biblioteca Polars para otimização. Apesar de alguns problemas de otimização, como a desconexão do notebook em algumas tentativas, ele reconecta automaticamente.
Agora, temos os dados mais delimitados, observando informações para números inteiros e do tipo float. Assim, os dados que estão em análise fazem mais sentido, como a média das unidades vendidas e o desvio padrão nessas unidades vendidas, além do lucro total, onde podemos acessar o mínimo do lucro total e identificar possíveis casos de prejuízo.
Outro ponto de interesse para verificar a qualidade dos dados é a presença de dados nulos no dataframe. Identificamos dados nulos com describe()
anteriormente, mas estavam relacionados a um cálculo indevido, realizado sobre texto, quando esperávamos uma variável numérica.
Agora, queremos verificar se, de forma geral no dataframe, existem dados nulos ou faltantes de algum tipo. Para isso, existe o método null_count()
, que podemos aplicar diretamente no dataframe (df
). Abaixo, temos o resultado do comando:
df.null_count()
Região | País | Tipo de Item | Canal de Venda | Prioridade do Pedido | Data do Pedido | ID do Pedido | Data de Envio | Unidades Vendidas | Preço Unitário | Custo Unitário | Receita Total | Custo Total | Lucro Total |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
u32 | u32 | u32 | u32 | u32 | u32 | u32 | u32 | u32 | u32 | u32 | u32 | u32 | u32 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Ao aplicar o método null_count()
, verificamos que todas as variáveis apresentam 0 valores nulos, ou seja, não há valores nulos no nosso dataframe.
No entanto, pode haver outro tipo de dado que o null_count()
não detecta, mas que ainda assim pode ser problemático: valores do tipo NaN.
Para verificar a existência desses valores, precisamos realizar um processamento adicional, pois não há um método específico no Polars para essa verificação.
Em uma nova célula, vamos criar a variável nan_counts
para verificar, coluna por coluna, se existe essa informação. Para isso, criaremos um dicionário que armazenará e exibirá as informações. A ideia é contar apenas os valores NaN, então usaremos a seguinte lógica:
nan_counts = {
col: (
(df[col].is_nan().sum() if df[col].dtype in (pl.Int64, pl.Float64) else 0)
+ df[col].is_null().sum()
)
for col in df.columns
}
É importante garantir que a operação seja realizada apenas em dados do tipo Int64
ou Float64
, pois o valor NaN aparece apenas em valores numéricos, não fazendo sentido no tipo string. Portanto, adicionamos uma condição para verificar o tipo de dado antes de realizar a soma.
Também podemos incluir valores do tipo null
na contagem com df[col].is_null().sum()
. Em seguida, fizemos um loop for
para percorrer as colunas do dataframe e verificar se cada valor é do tipo NaN, somando-os para obter o total de números do tipo NaN em cada coluna.
Após executar e imprimir com nan_counts
, verificamos que todos os valores são 0, indicando que não há dados nulos nem valores do tipo NaN no conjunto. Isso significa que podemos prosseguir para as próximas etapas do processamento dos dados.
nan_counts
Retorno do comando:
{'Região': 0,
'País': 0,
'Tipo de Item': 0,
'Canal de Venda': 0,
'Prioridade do Pedido': 0,
'Data do Pedido': 0,
'ID do Pedido': 0,
'Data de Envio': 0,
'Unidades Vendidas': 0,
'Preço Unitário': 0,
'Custo Unitário': 0,
'Receita Total': 0,
'Custo Total': 0,
'Lucro Total': 0}
Neste vídeo, realizamos algumas etapas de seleção dos dados. No próximo vídeo, começaremos a explorar como fazer seleções mais específicas para focar no problema que queremos resolver!
O curso Polars: manipulando tabelas possui 121 minutos de vídeos, em um total de 48 atividades. Gostou? Conheça nossos outros cursos de Data Science em Data Science, ou leia nossos artigos de Data Science.
Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:
Impulsione a sua carreira com os melhores cursos e faça parte da maior comunidade tech.
1 ano de Alura
Assine o PLUS e garanta:
Formações com mais de 1500 cursos atualizados e novos lançamentos semanais, em Programação, Inteligência Artificial, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.
A cada curso ou formação concluído, um novo certificado para turbinar seu currículo e LinkedIn.
No Discord, você tem acesso a eventos exclusivos, grupos de estudos e mentorias com especialistas de diferentes áreas.
Faça parte da maior comunidade Dev do país e crie conexões com mais de 120 mil pessoas no Discord.
Acesso ilimitado ao catálogo de Imersões da Alura para praticar conhecimentos em diferentes áreas.
Explore um universo de possibilidades na palma da sua mão. Baixe as aulas para assistir offline, onde e quando quiser.
Acelere o seu aprendizado com a IA da Alura e prepare-se para o mercado internacional.
1 ano de Alura
Todos os benefícios do PLUS e mais vantagens exclusivas:
Luri é nossa inteligência artificial que tira dúvidas, dá exemplos práticos, corrige exercícios e ajuda a mergulhar ainda mais durante as aulas. Você pode conversar com a Luri até 100 mensagens por semana.
Aprenda um novo idioma e expanda seus horizontes profissionais. Cursos de Inglês, Espanhol e Inglês para Devs, 100% focado em tecnologia.
Transforme a sua jornada com benefícios exclusivos e evolua ainda mais na sua carreira.
1 ano de Alura
Todos os benefícios do PRO e mais vantagens exclusivas:
Mensagens ilimitadas para estudar com a Luri, a IA da Alura, disponível 24hs para tirar suas dúvidas, dar exemplos práticos, corrigir exercícios e impulsionar seus estudos.
Envie imagens para a Luri e ela te ajuda a solucionar problemas, identificar erros, esclarecer gráficos, analisar design e muito mais.
Escolha os ebooks da Casa do Código, a editora da Alura, que apoiarão a sua jornada de aprendizado para sempre.