Ciência de dados com pandas
A ciência de dados é um campo multidisciplinar e muito importante nos nossos dias. Ela tem como objetivos descobrir anomalias e padrões escondidos em grandes quantidades de dados (“Big Data”) através de técnicas de modelagem e análise. Em postagens anteriores, exploramos a área através da biblioteca pandas. Neste post, terminaremos nossa exploração apresentando os métodos do pandas voltados para manipulação e transformações de dados. Este post assume familiaridade com os conceitos apresentados anteriormente (aqui, aqui e aqui).
Manipulações de dados com pandas
Para acompanhar nossa exploração do pandas, é preciso importar a biblioteca num código Python.
import pandas as pd
Também precisaremos de alguns dados. Começaremos com os dados abaixo. Para usá-los, basta copiá-los no seu arquivo Python.
data = {
'Estado': ['SP', 'RJ', 'RS', 'SP', 'CE', 'RJ', 'CE'],
'Produto': ['A', 'B', 'A', 'C', 'A', 'B', 'C'],
'Vendas': [100, 50, 120, None, 80, None, 40],
'Mês': ['Jan', 'Jan', 'Fev', 'Fev', 'Jan', 'Fev', 'Fev']
}
Como explicado anteriormente, os dados precisam ser abertos com o pandas.
df = pd.DataFrame(data)
Nossos dados possuem valores ausentes (None). Usaremos o comando fillna() para substituí-los por zeros.
df_preenchido = df.fillna(0)
groupby()
Nossa primeira exploração será do comando groupby(). Uma operação groupby pode envolver múltiplas tarefas combinadas, como dividir dados, aplicar cálculos e recombinar os resultados. Essa é uma forma conveniente para agrupar grandes quantidades de dados e, simultaneamente, realizar computação nesses grupos. Na prática, o método groupby() não modifica o DataFrame, ele apenas cria um objeto groupby de agregação. Essa agregação é comumente usada para realizar operações subsequentes concisamente. No exemplo abaixo, usamos o comando groupby sobre nossos dados para verificar a média de vendas por estado. Veja que as colunas são diretamente selecionadas por seus nomes.
# agrupa por estado e acha a média de vendas
media_vendas_por_estado = df_preenchido.groupby('Estado')['Vendas'].mean()
print(media_vendas_por_estado)
Estado
CE 60.0
RJ 25.0
RS 120.0
SP 50.0
Name: Vendas, dtype: float64
Abaixo, um exemplo de agrupamento mais complexo. Nesse exemplo, o groupby é usado para agregar as vendas nos estados por mês e depois calcular sua soma.
# agrupa por estado e mês para obter a soma de vendas
sales_by_product_month = df_preenchido.groupby(['Produto', 'Mês'])['Vendas'].sum()
print(sales_by_product_month)
Produto Mês
A Fev 120.0
Jan 180.0
B Fev 0.0
Jan 50.0
C Fev 40.0
Name: Vendas, dtype: float64
O groupby também pode ser usado com múltiplas operações agregadas. Para isso, no exemplo abaixo, o groupby é usado em combinação com agg(). O agg() aplica uma lista de funções sobre os elementos agregados. Aplicaremos três funções para calcular o mínimo de vendas (min), máximo de vendas (max) e a contagem de meses com vendas para cada estado.
# agrupa por estado e acha dados estatísticos sobre as vendas
estat_vendas_por_estado = df_preenchido.groupby('Estado')['Vendas'].agg(['min', 'max', 'count'])
print(estat_vendas_por_estado)
min max count
Estado
CE 40.0 80.0 2
RJ 0.0 50.0 2
RS 120.0 120.0 1
SP 0.0 100.0 2
O groupby também pode ser usado com funções personalizadas. No exemplo abaixo, utilizamos groupby com uma função que retorna o máximo de vendas para cada estado.
def top_estado_vendas(group):
return group.nlargest(1).iloc[0] # Retorna valor máximo de vendas por estado
resultados = df_preenchido.groupby('Estado')['Vendas'].apply(top_estado_vendas)
print(resultados)
Na função acima, note que usamos o iloc combinado com nlargest() para retornar especificamente o valor (iloc) máximo (nlargest) encontrado. Os resultados obtidos:
Estado
CE 80.0
RJ 50.0
RS 120.0
SP 100.0
Name: Vendas, dtype: float64
sort_value()
O comando sort_value() organiza um DataFrame a partir da ordem (ascendente ou descendente) de uma ou mais colunas. Abaixo, ele é utilizado para organizar nossos dados a partir dos valores de vendas.
# ordena dados pelos valores de Vendas
df_reordenado = df_preenchido.sort_values(by=['Vendas'])
print(df_reordenado)
Estado Produto Vendas Mês
3 SP C 0.0 Fev
5 RJ B 0.0 Fev
6 CE C 40.0 Fev
1 RJ B 50.0 Jan
4 CE A 80.0 Jan
0 SP A 100.0 Jan
2 RS A 120.0 Fev
A opção default do sort_value() organiza os dados de maneira ascendente. Mas ela é facilmente alterada com a opção ascending=False.
# ordena dados pelos valores de Vendas em ordem decrescente
df_reordenado = df_preenchido.sort_values(by=['Vendas'], ascending=False)
print(df_reordenado)
Note que, nos resultados abaixo, o pandas reordenou os dados, mas manteve os índices originais. Quando isso não é desejado, basta adicionar no comando sort_values a opção ignore_index=True.
Estado Produto Vendas Mês
2 RS A 120.0 Fev
0 SP A 100.0 Jan
4 CE A 80.0 Jan
1 RJ B 50.0 Jan
6 CE C 40.0 Fev
3 SP C 0.0 Fev
5 RJ B 0.0 Fev
concat()
Em ciência de dados ou mesmo durante a obtenção e preparação de dados para treinamento de algoritmos de machine learning, a combinação de múltiplos conjuntos é uma atividade corriqueira. Como os conjuntos tendem a ser grandes, ninguém deve fazer isso manualmente. O pandas simplifica essa tarefa com o comando concat(). Ele faz o óbvio: combina múltiplos conjuntos de dados em um. Para nosso exemplo, criamos um novo conjunto para ser combinado com o anterior. Antes da combinação, fizemos novamente a substituição de valores ausentes por zero com fillna().
data2 = {
'Estado': ['ES', 'AM', 'PA', 'ES', 'AM', 'RJ'],
'Produto': ['C', 'A', 'B', 'B', 'B', 'C'],
'Vendas': [80, None, 20, 10, 50, 25],
'Mês': ['Mar', 'Abr', 'Fev', 'Abr', 'Mar', 'Mar']
}
df2 = pd.DataFrame(data2)
df_preenchido2 = df2.fillna(0)
# concatena os conjuntos df_preenchido e df_preenchido2
dados_completos = pd.concat([df_preenchido, df_preenchido2], ignore_index=True)
print(dados_completos)
No trecho acima, a opção ignore_index=True ignora os índices dos conjuntos que estão sendo combinados e cria um novo índice no conjunto final mostrado abaixo.
Estado Produto Vendas Mês
0 SP A 100.0 Jan
1 RJ B 50.0 Jan
2 RS A 120.0 Fev
3 SP C 0.0 Fev
4 CE A 80.0 Jan
5 RJ B 0.0 Fev
6 CE C 40.0 Fev
7 ES C 80.0 Mar
8 AM A 0.0 Abr
9 PA B 20.0 Fev
10 ES B 10.0 Abr
11 AM B 50.0 Mar
12 RJ C 25.0 Mar
apply()
A funcionalidade apply() é uma das mais úteis do pandas para tarefas de machine learning. Ela é particularmente útil para pré-processamentos de dados e é frequentemente usada, inclusive com dados de textos, para processamento de linguagem natural. Em essência, o comando apply() aplica funções diretamente num DataFrame ou (mais comum) em colunas ou linhas específicas.
No trecho abaixo, criamos uma função que calcula o lucro sobre nossas vendas. Ela é diretamente aplicada nos dados (coluna Vendas) e já cria uma nova coluna com os resultados.
def calcula_lucro(vendas, margem=0.3):
return vendas * margem
# aplica função que calcula o lucro sobre as vendas
dados_completos['Lucro'] = dados_completo['Vendas'].apply(calcula_lucro)
print(dados_completos)
Os resultados com uma nova coluna (Lucro).
Estado Produto Vendas Mês Lucro
0 SP A 100.0 Jan 30.0
1 RJ B 50.0 Jan 15.0
2 RS A 120.0 Fev 36.0
3 SP C 0.0 Fev 0.0
4 CE A 80.0 Jan 24.0
5 RJ B 0.0 Fev 0.0
6 CE C 40.0 Fev 12.0
7 ES C 80.0 Mar 24.0
8 AM A 0.0 Abr 0.0
9 PA B 20.0 Fev 6.0
10 ES B 10.0 Abr 3.0
11 AM B 50.0 Mar 15.0
12 RJ C 25.0 Mar 7.5
A opção default do comando apply() realiza os cálculos de uma função em uma ou mais colunas, mas isso pode ser mudado com a opção axis=1. Nesse caso, a função será aplicada nas linhas.
No trecho abaixo, nossa nova função tem um condicional que classifica o volume de vendas. Ela é diretamente aplicada nos dados, mas especificamente sobre suas linhas.
def categoriza_vendas(row):
if row['Vendas'] > 100:
return 'Alto'
elif row['Vendas'] > 50:
return 'Médio'
else:
return 'Baixo'
# aplica função que categoriza as vendas
dados_completos['Desempenho das Vendas'] = dados_completos.apply(categoriza_vendas, axis=1)
#print(dados_completos)
Estado Produto Vendas Mês Lucro Desempenho das Vendas
0 SP A 100.0 Jan 30.0 Médio
1 RJ B 50.0 Jan 15.0 Baixo
2 RS A 120.0 Fev 36.0 Alto
3 SP C 0.0 Fev 0.0 Baixo
4 CE A 80.0 Jan 24.0 Médio
5 RJ B 0.0 Fev 0.0 Baixo
6 CE C 40.0 Fev 12.0 Baixo
7 ES C 80.0 Mar 24.0 Médio
8 AM A 0.0 Abr 0.0 Baixo
9 PA B 20.0 Fev 6.0 Baixo
10 ES B 10.0 Abr 3.0 Baixo
11 AM B 50.0 Mar 15.0 Baixo
12 RJ C 25.0 Mar 7.5 Baixo
Conclusões
Com esse post, encerramos nossa exploração do pacote pandas. Mas não pense que fomos muito longe. O pandas é um pacote enorme, fácil de usar e extremamente poderoso. Por isso, se você tem interesse em machine learning, inteligência artificial ou ciência de dados, confira a documentação oficial e busque aprender mais sobre ele.