Entenda como deixar o seu código Pandas mais rápido e eficiente utilizando as operações vetorizadas, um importante recurso para trabalhar com dados.
Caso prefira esse conteúdo no formato de vídeo-aula, assista ao vídeo abaixo ou acesse o nosso canal do YouTube!
Para receber por e-mail o(s) arquivo(s) utilizados na aula, preencha:
Operações Vetorizadas – Deixando Código Pandas Mais Rápido
Na aula de hoje, quero te mostrar como melhorar seu código Pandas, tornando-o mais rápido e eficiente, utilizando as operações vetorizadas.
A biblioteca Pandas é uma das mais importantes em Python quando estamos trabalhando com dados. Ela oferece muitos recursos que permitem aumentar a eficiência do código e a velocidade com que tratamos os dados.
Vou te mostrar como usar um desses recursos, as operações vetorizadas, e demonstrar como elas podem aumentar a eficiência e a velocidade do seu código.
Ficou curioso? Quer aprender a acelerar seus códigos Pandas e construir análises de dados de forma muito mais rápida e eficiente? Então faça o download do material disponível e venha comigo que eu vou te mostrar como!
Análise da Base de Dados – Criando o DataFrame
Ao longo desta aula, utilizaremos uma base de dados que traz as transações comerciais de uma empresa.
Nela, teremos informações como o ID do cliente, a data da transação, a categoria do produto, a idade, o gênero, o preço do produto e a quantidade comprada.
Vamos criar nosso DataFrame utilizando o Pandas e visualizar as informações da nossa base de dados.
import pandas as pd
BASE = "./dados/dados_transacoes.csv"
df = pd.read_csv(BASE)
df
df.info()
Repare que essa é uma base de dados relativamente pequena, com 50 mil linhas. Mas será o suficiente para que eu possa te mostrar as vantagens de utilizar as operações vetorizadas com Pandas.
Muitas pessoas estão migrando para a área de dados. Algumas nunca tiveram contato com programação, enquanto outras já possuem uma certa bagagem, mas em áreas diferentes.
Nesses cenários, as pessoas acabam por começar estudando Python e, quando entram em contato com a parte de dados e a biblioteca Pandas, tentam replicar as estruturas básicas que aprenderam com Python dentro do Pandas.
Isso acaba resultando em códigos que, na prática, funcionam, mas não são tão eficientes e rápidos quanto poderiam ser se tivessem sido escritos da forma mais adequada.
Por isso, nesta aula, eu vou te apresentar três formas diferentes de escrever o mesmo código: uma utilizando a estrutura básica do For, outra usando a função Apply do Pandas e, por fim, utilizando as estruturas vetorizadas.
Coluna Total Usando For
Para o nosso exemplo, vamos desenvolver um código que calcule o total pago por cada cliente e crie uma coluna no DataFrame com esse valor.
Muitos iniciantes, quando se deparam com uma situação como essa, recorrem à estrutura For do Python, criando um loop que percorrerá cada uma das linhas, pegará o valor na coluna preco e multiplicará pelo valor na coluna quantidade.
Apesar da linha de raciocínio estar correta, essa não é a forma mais eficiente de se fazer isso. E eu vou te mostrar o porquê isso não é recomendado, cronometrando o tempo de execução desse e dos outros códigos.
Para isso, vamos utilizar um comando do Jupyter Notebook que é o %%timeit, que serve para cronometrar o tempo de execução de um código. Ele rodará essa célula várias vezes e apresentará a média de tempo gasto.
Nosso loop For irá iterar sobre cada linha (i), ou seja, cada número gerado por range(len(df)).
Dessa forma, percorreremos todas as linhas do DataFrame e, para cada linha, vamos criar uma coluna chamada total_for com o resultado da multiplicação entre o valor contido nessa linha para a coluna quantidade e preco.
%%timeit
# for loop para calcular o total de vendas de cada transação (quantidade * preço) e adicionar em uma nova coluna
# pouco eficiente, evitar
for i in range(len(df)):
df.loc[i, "total_for"] = df.loc[i, "quantidade"] * df.loc[i, "preco"]
Feito isso, vamos executar o código e aguardar até que o comando %%timeit faça as execuções necessárias e calcule o tempo.
Você poderá perceber que essa execução será mais demorada que o normal, pois o Jupyter executará a célula diversas vezes para poder calcular a média.
Então, repare que ele executou esse código 7 vezes (7 runs) e a média de tempo gasto foi de 3,11 segundos, com um desvio padrão de 17,6 milissegundos.
Considerando que nosso DataFrame tem apenas 50 mil linhas, gastar uma média de 3 segundos para realizar esses cálculos e construir uma nova coluna é um tempo significativamente grande.
Principalmente por estarmos utilizando o Pandas para fazer esse procedimento, ele poderia ser muito mais rápido. E essa diferença pode ficar ainda mais evidente se lidarmos com bases de dados muito maiores do que essa.
A dica que eu posso deixar aqui é: toda vez que você pensar em percorrer cada uma das linhas de um DataFrame realizando alguma ação, essa provavelmente não é a melhor forma de escrever esse código em Pandas.
Deixando claro que você conseguirá obter o resultado desejado, porém, não será da forma mais rápida e eficiente.
Veja, a coluna foi criada normalmente como o esperado.
Coluna Total com Apply
A segunda forma que temos de realizar essa operação, que será mais eficiente que a anterior, é criando uma função e aplicando-a em todo o DataFrame através da função Apply do Pandas.
Essa função recebe como argumento uma função que será aplicada ao longo de todo um eixo do DataFrame, que nesse caso será o eixo 1 (axis=1) referente às linhas.
A função que iremos aplicar será uma função lambda que pega uma linha do DataFrame e calcula o produto dos valores nas colunas quantidade e preco.
Para calcular o tempo, vamos usar novamente o comando %%timeit.
%%timeit
# uso de apply. Mais eficiente, mas ainda não é a melhor opção
df["total_apply"] = df.apply(
lambda linha: linha["quantidade"] * linha["preco"], axis=1
)
Repare que agora a média de tempo gasto por loop foi de 182 milissegundos, com um desvio padrão de 4.29 milissegundos.
E assim como no método anterior, também teremos a coluna criada no nosso DataFrame como o esperado.
E esse tempo pode ser ainda menor se utilizarmos as operações vetorizadas com Pandas.
Operações Vetorizadas com Pandas
Quando acessamos uma coluna específica de um DataFrame, estamos acessando uma série do Pandas. Uma série no Pandas é construída em cima de outras ferramentas como os arrays do NumPy ou do PyArrow.
Os arrays podem ser traduzidos como vetores e são estruturas de dados que possuem um tamanho e um tipo definido. Por exemplo, a coluna preco pode ter 50 mil linhas com números do tipo float.
df["preco"]
Por isso, chamamos de operações vetorizadas os cálculos e operações que realizamos diretamente sobre as séries do Pandas. Essas operações permitem que façamos cálculos em todos os elementos da série de uma só vez, de maneira rápida e eficiente.
Então poderíamos calcular a coluna total da seguinte forma:
%%timeit
# operação vetorizada
df["total_vetorizado"] = df["quantidade"] * df["preco"]
Perceba que nesse caso, a média do tempo gasto foi de 121 microssegundos com um desvio padrão de 551 nanossegundos. Para ter uma comparação, 1 segundo equivale a 1 milhão de microssegundos.
Isso é possível porque o Pandas, o NumPy e o PyArrow, bibliotecas que utilizam estruturas de arrays, são otimizadas para que operações como essa possam ser realizadas.
Sempre que fizermos as operações diretamente dessa forma, utilizando os vetores, elas serão muito mais rápidas e eficientes.
Categoria de Produtos na Base de Dados – Calculando Desconto
Para o nosso próximo exemplo, trabalharemos com as categorias presentes nessa base de dados. Então, primeiro vamos visualizá-las utilizando o método unique.
df["categoria_produto"].unique()
Digamos que, para cada categoria, queremos definir um desconto específico no valor do produto. Vamos definir esse desconto dentro de um dicionário Python.
descontos_categorias = {
"Eletrônicos": 0.1,
"Alimentos": 0.05,
"Roupas": 0.15,
"Casa & Cozinha": 0.2,
"Livros": 0.25,
}
Agora, precisamos associar cada um desses descontos a uma categoria, criando uma nova coluna na base de dados com os preços após o desconto aplicado.
Um iniciante poderia pensar novamente em criar um loop for, olhando para cada linha, procurando a categoria e associando a categoria com o desconto. E a partir disso, criar uma nova coluna com o preço e o desconto aplicado.
Porém, dentro do Pandas temos ferramentas mais eficientes para fazer isso. A primeira parte podemos fazer utilizando o método map. Esse método recebe um dicionário e, a partir dele, associa os valores contidos na chave e no valor com o DataFrame.
Dessa forma, o método map criará automaticamente uma série com cada um dos descontos aplicados na ordem em que as categorias são exibidas no DataFrame.
df["categoria_produto"].map(descontos_categorias)
Perceba que agora temos um vetor representando os descontos que queremos aplicar. Dessa forma, para criar a coluna com os preços com desconto, podemos utilizar uma operação vetorizada de forma simples e eficiente.
%%timeit
# criar coluna com o preco com desconto com operaçao vetorizada
df["preco_desconto"] = df["preco"] * (1 - df["categoria_produto"].map(descontos_categorias))
df
Veja como foi extremamente rápido criar a coluna e realizar os cálculos para o preço com desconto.
Conclusão – Operações Vetorizadas – Deixando Código Pandas Mais Rápido
Na aula de hoje, eu te mostrei como melhorar seu código Pandas, tornando-o mais rápido e eficiente utilizando as operações vetorizadas.
É comum pensarmos em utilizar loops for em Python quando estamos iniciando em análise de dados e códigos com Pandas, mas é muito recomendado evitar usá-los devido à baixa eficiência em comparação aos outros métodos.
As operações vetorizadas são um recurso muito importante e eficiente dentro da análise de dados. E quando não for possível, uma melhor opção é utilizar a função apply.
Nessa aula, você viu o que são operações vetorizadas e por que elas são mais eficientes e recomendadas para serem utilizadas no tratamento e trabalho com dados.
Hashtag Treinamentos
Para acessar outras publicações de Ciência de Dados, clique aqui!
Expert em conteúdos da Hashtag Treinamentos. Auxilia na criação de conteúdos de variados temas voltados para aqueles que acompanham nossos canais.