Alura > Cursos de Data Science > Cursos de Data Science > Conteúdos de Data Science > Primeiras aulas do curso Polars: manipulando tabelas

Polars: manipulando tabelas

Leitura de arquivos com o Polars - Apresentação

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.

O que vamos aprender?

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.

Conclusão

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!

Leitura de arquivos com o Polars - Passando um arquivo para o DataFrame

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.

Passando um arquivo para o dataframe

Localizando o dataset no Google Drive

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'

Importando a biblioteca 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

Extraindo o conteúdo do arquivo ZIP

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)

Importando a biblioteca Polars

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

Declarando a variável 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'

Definindo o dataframe

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()

Visualizando o resultado

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ãoPaísTipo de ItemCanal de VendaPrioridade do PedidoData do PedidoID do PedidoData de EnvioUnidades VendidasPreço UnitárioCusto UnitárioReceita TotalCusto TotalLucro Total
strstrstrstrstrstri64stri64f64f64f64f64f64
"Australia and Oceania""Palau""Office Supplies""Online""H""3/6/2016"517073523"3/26/2016"2401651.21524.961.2508e61.2604e6-9584.792
"Europe""Poland""Beverages""Online""L""4/18/2010"380507028"5/26/2010"934047.4531.79354546.4296918.657627.8
"North America""Canada""Cereal""Online""M""1/8/2015"504055583"1/31/2015"103205.7117.1116949.6812062.334887.35
"Europe""Belarus""Snacks""Online""C""1/19/2014"954955518"2/27/2014"1414152.5897.44172598.496137780.1634818.336
"Middle East and North Africa""Oman""Cereal""Offline""H""4/26/2019"970755660"6/2/2019"7027205.7117.111.1564e6822931.97333431.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.

Conclusão

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!

Leitura de arquivos com o Polars - Analisando os dados

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.

Analisando os dados

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ãoPaísTipo de ItemCanal de VendaPrioridade do PedidoData do PedidoID do PedidoData de EnvioUnidades VendidasPreço UnitárioCusto UnitárioReceita TotalCusto TotalLucro Total
strstrstrstrstrstri64stri64f64f64f64f64f64
"Australia and Oceania""Palau""Office Supplies""Online""H""3/6/2016"517073523"3/26/2016"2401651.21524.961.2508e61.2604e6-9584.792
"Europe""Poland""Beverages""Online""L""4/18/2010"380507028"5/26/2010"934047.4531.79354546.4296918.657627.8
"North America""Canada""Cereal""Online""M""1/8/2015"504055583"1/31/2015"103205.7117.1116949.6812062.334887.35
"Europe""Belarus""Snacks""Online""C""1/19/2014"954955518"2/27/2014"1414152.5897.44172598.496137780.1634818.336
"Middle East and North Africa""Oman""Cereal""Offline""H""4/26/2019"970755660"6/2/2019"7027205.7117.111.1564e6822931.97333431.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.

Utilizando o comando 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]

Utilizando o método 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()
statisticRegiãoPaísTipo de ItemCanal de VendaPrioridade do PedidoData do PedidoID do PedidoData de EnvioUnidades VendidasPreço UnitárioCusto UnitárioReceita TotalCusto TotalLucro Total
strstrstrstrstrstrstrf64strf64f64f64f64f64f64
"count""5000000""5000000""5000000""5000000""5000000""5000000"5e6"5000000"5e65e65e65e65e65e6
"null_count""0""0""0""0""0""0"0.0"0"0.00.00.00.00.00.0
"mean"nullnullnullnullnullnull5.4989e8null4999.991061266.190616187.6559911.1439e6938378.122412205508.425247
"std"nullnullnullnullnullnull2.5978e8null2886.787007217.015273175.7013791.3158e61.1501e6451094.254368
"min""Asia""Afghanistan""Baby Food""Offline""C""1/1/2010"1.00000321e8"1/1/2010"1.09.336.927.4646.92-271780.0
"25%"nullnullnullnullnullnull3.24965131e8null2500.0109.2856.67231366.2161925.125065.57
"50%"nullnullnullnullnullnull5.49764287e8null4999.0205.7117.11658009.728467712.080190.0
"75%"nullnullnullnullnullnull7.74837243e8null7500.0437.2364.691.5568e61.1974e6258412.7
"max""Sub-Saharan Africa""Zimbabwe""Vegetables""Online""M""9/9/2020"9.99999892e8"9/9/2020"10000.0668.27524.961.002405e75.2496e64.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.

Selecionando apenas valores inteiros e do tipo float

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()
statisticID do PedidoUnidades VendidasPreço UnitárioCusto UnitárioReceita TotalCusto TotalLucro Total
strf64f64f64f64f64f64f64
"count"5e65e65e65e65e65e65e6
"null_count"0.00.00.00.00.00.00.0
"mean"5.4989e84999.991061266.190616187.6559911.1439e6938378.122412205508.425247
"std"2.5978e82886.787007217.015273175.7013791.3158e61.1501e6451094.254368
"min"1.00000321e81.09.336.927.4646.92-271780.0
"25%"3.24965131e82500.0109.2856.67231366.2161925.125065.57
"50%"5.49764287e84999.0205.7117.11658009.728467712.080190.0
"75%"7.74837243e87500.0437.2364.691.5568e61.1974e6258412.7
"max"9.99999892e810000.0668.27524.961.002405e75.2496e64.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.

Verificando dados nulos no dataframe

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ãoPaísTipo de ItemCanal de VendaPrioridade do PedidoData do PedidoID do PedidoData de EnvioUnidades VendidasPreço UnitárioCusto UnitárioReceita TotalCusto TotalLucro Total
u32u32u32u32u32u32u32u32u32u32u32u32u32u32
00000000000000

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}

Conclusão

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!

Sobre o curso Polars: manipulando tabelas

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:

Aprenda Data Science acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas