Tutorial de Pandas
Aprenda pandas do zero: Series, DataFrames, filtragem, groupby, valores ausentes, mesclagem e visualização de dados com exemplos Python claros.
pandas é a biblioteca Python mais utilizada para trabalhar com dados estruturados (tabulares). Ela fornece duas estruturas de dados centrais — Series e DataFrame — além de um rico conjunto de ferramentas para carregar, limpar, transformar, agregar e visualizar dados.
Este capítulo aborda tudo o que você precisa saber para ir do zero à produtividade com pandas: instalação, estruturas de dados, leitura de arquivos, seleção e filtragem de dados, tratamento de valores ausentes, agrupamento, mesclagem e plotagem básica.
Instalando o pandas
Instale o pandas com pip:
pip install pandasSe você planeja seguir os exemplos de plotagem mais adiante neste capítulo, instale também o Matplotlib:
pip install matplotlibApós a instalação, importe o pandas usando o alias convencional pd:
import pandas as pdAs Duas Estruturas de Dados Centrais
Series
Uma Series é um array unidimensional com rótulos. Cada elemento possui um valor e um rótulo de índice correspondente (por padrão, inteiros começando em 0).
import pandas as pd
scores = pd.Series([88.5, 92.0, 79.5, 95.0])
print(scores)Saída:
0 88.5
1 92.0
2 79.5
3 95.0
dtype: float64Você pode fornecer rótulos de índice personalizados para tornar os dados autodescritivos:
scores = pd.Series(
[88.5, 92.0, 79.5, 95.0],
index=['Alice', 'Bob', 'Carol', 'Dave']
)
print(scores)
print(scores['Bob']) # 92.0Saída:
Alice 88.5
Bob 92.0
Carol 79.5
Dave 95.0
dtype: float64
92.0Uma Series com um índice significativo é semelhante a um dicionário Python, mas suporta operações vetorizadas e está integrada ao restante da API do pandas.
DataFrame
Um DataFrame é uma tabela bidimensional com linhas e colunas rotuladas — pense nele como uma planilha ou uma tabela SQL carregada no Python. Cada coluna é internamente uma Series que compartilha o mesmo índice de linhas.
Criando um DataFrame a partir de um dicionário de listas
Saída:
name age score
0 Alice 25 88.5
1 Bob 30 92.0
2 Carol 28 79.5
3 Dave 35 95.0As chaves do dicionário tornam-se nomes de colunas; os valores do dicionário tornam-se as colunas. O índice de linhas é, por padrão, 0, 1, 2, 3.
Atributos úteis para inspecionar um DataFrame logo após a criação:
| Atributo / Método | O que retorna |
|---|---|
df.shape | Tupla de (rows, columns) |
df.dtypes | Tipo de dado de cada coluna |
df.columns | Rótulos das colunas |
df.index | Rótulos das linhas |
df.head(n) | Primeiras n linhas (padrão 5) |
df.tail(n) | Últimas n linhas (padrão 5) |
df.describe() | Estatísticas resumidas para colunas numéricas |
df.info() | Nomes das colunas, tipos e contagens não nulas |
Lendo Dados de Arquivos
Em projetos reais, você raramente cria DataFrames manualmente. O pandas pode ler dezenas de formatos de arquivo.
Lendo um arquivo CSV
import pandas as pd
df = pd.read_csv('sales.csv')
print(df.head())
print(df.shape) # e.g. (1000, 5)
print(df.dtypes)pd.read_csv() infere automaticamente os tipos das colunas. Opções comuns:
sep=';'— alterar o delimitador (padrão é vírgula)index_col='id'— usar uma coluna como índice de linhasparse_dates=['date']— analisar uma coluna como datetimenrows=500— ler apenas as primeiras 500 linhas (útil para arquivos grandes)
Lendo um arquivo Excel
df = pd.read_excel('report.xlsx', sheet_name='Sheet1')Requer a dependência opcional openpyxl: pip install openpyxl.
Gravando dados de volta em um arquivo
df.to_csv('output.csv', index=False) # CSV without the row index column
df.to_excel('output.xlsx', index=False) # ExcelSelecionando Dados
Selecionando colunas
Selecione uma única coluna para obter uma Series:
ages = df['age']
print(type(ages)) # <class 'pandas.core.series.Series'>Selecione múltiplas colunas para obter um DataFrame:
subset = df[['name', 'score']]
print(subset)Saída:
name score
0 Alice 88.5
1 Bob 92.0
2 Carol 79.5
3 Dave 95.0Selecionando linhas com loc e iloc
O pandas fornece dois seletores principais de linhas:
loc— seleciona por rótulo (valor do índice)iloc— seleciona por posição inteira (baseado em 0)
import pandas as pd
data = {
'name': ['Alice', 'Bob', 'Carol', 'Dave'],
'age': [25, 30, 28, 35],
'score': [88.5, 92.0, 79.5, 95.0],
}
df = pd.DataFrame(data)
print(df.loc[1]) # row with index label 1
print()
print(df.iloc[0]) # first row by position
print()
print(df.loc[1:2]) # rows with labels 1 and 2 (inclusive)
print()
print(df.iloc[0:2]) # rows at positions 0 and 1 (end is exclusive)Saída:
name Bob
age 30
score 92.0
Name: 1, dtype: object
name Alice
age 25
score 88.5
Name: 0, dtype: object
name age score
1 Bob 30 92.0
2 Carol 28 79.5
name age score
0 Alice 25 88.5
1 Bob 30 92.0Observe a diferença: loc[1:2] é baseado em rótulo e inclusivo em ambas as extremidades; iloc[0:2] é baseado em posição e exclusivo na extremidade direita (como fatias regulares do Python).
Você também pode selecionar uma célula específica:
print(df.loc[1, 'score']) # 92.0 — by label
print(df.iloc[0, 2]) # 88.5 — by positionFiltrando Linhas
Filtre linhas usando uma condição booleana dentro de colchetes:
import pandas as pd
data = {
'name': ['Alice', 'Bob', 'Carol', 'Dave'],
'age': [25, 30, 28, 35],
'score': [88.5, 92.0, 79.5, 95.0],
}
df = pd.DataFrame(data)
# Rows where age is greater than 28
print(df[df['age'] > 28])Saída:
name age score
1 Bob 30 92.0
3 Dave 35 95.0Combine múltiplas condições com & (e) ou | (ou). Sempre envolva cada condição em parênteses:
# Age > 25 AND score >= 90
print(df[(df['age'] > 25) & (df['score'] >= 90)])Saída:
name age score
1 Bob 30 92.0
3 Dave 35 95.0Use isin() para filtrar por uma lista de valores:
print(df[df['name'].isin(['Alice', 'Carol'])])Adicionando e Modificando Colunas
Adicione uma nova coluna atribuindo a ela:
import pandas as pd
data = {
'name': ['Alice', 'Bob', 'Carol', 'Dave'],
'age': [25, 30, 28, 35],
'score': [88.5, 92.0, 79.5, 95.0],
}
df = pd.DataFrame(data)
# Add a column with a calculated value
df['grade'] = df['score'].apply(lambda x: 'A' if x >= 90 else 'B')
print(df)Saída:
name age score grade
0 Alice 25 88.5 B
1 Bob 30 92.0 A
2 Carol 28 79.5 B
3 Dave 35 95.0 Aapply() executa uma função em cada elemento de uma coluna. Para aritmética simples, você pode usar operações vetorizadas diretamente — elas são mais rápidas que apply():
df['score_scaled'] = df['score'] / 100 # no apply() neededRenomeie colunas com rename():
df = df.rename(columns={'score': 'exam_score', 'age': 'years_old'})Remova uma coluna com drop():
df = df.drop(columns=['grade'])Ordenando Dados
Ordene um DataFrame por uma ou mais colunas usando sort_values():
import pandas as pd
data = {
'department': ['Eng', 'Eng', 'HR', 'HR', 'Eng'],
'name': ['Alice', 'Bob', 'Carol', 'Dave', 'Eve'],
'salary': [90000, 95000, 70000, 72000, 88000],
}
df = pd.DataFrame(data)
print(df.sort_values('salary', ascending=False))Saída:
department name salary
1 Eng Bob 95000
0 Eng Alice 90000
4 Eng Eve 88000
3 HR Dave 72000
2 HR Carol 70000Ordene por múltiplas colunas — por exemplo, departamento em ordem crescente e salário em ordem decrescente dentro de cada departamento:
df_sorted = df.sort_values(['department', 'salary'], ascending=[True, False])
print(df_sorted)Tratando Valores Ausentes
Conjuntos de dados do mundo real quase sempre contêm valores ausentes. O pandas os representa como NaN (Not a Number).
import pandas as pd
data = {
'name': ['Alice', 'Bob', 'Carol', 'Dave'],
'age': [25, None, 28, 35],
'score': [88.5, 92.0, None, 95.0],
}
df = pd.DataFrame(data)
# Count missing values per column
print(df.isnull().sum())Saída:
name 0
age 1
score 1
dtype: int64Preenchendo valores ausentes
Substitua NaN por um valor fixo ou uma estatística:
df_filled = df.fillna({
'age': df['age'].mean(), # fill with column mean
'score': df['score'].median() # fill with column median
})
print(df_filled)Saída:
name age score
0 Alice 25.000000 88.5
1 Bob 29.333333 92.0
2 Carol 28.000000 92.0
3 Dave 35.000000 95.0Removendo linhas com valores ausentes
df_dropped = df.dropna()
print(df_dropped)Saída:
name age score
0 Alice 25.0 88.5
3 Dave 35.0 95.0Quando preencher vs. quando remover: remover linhas perde dados e pode introduzir viés se os valores não estiverem ausentes aleatoriamente. Preencher (imputação) geralmente é preferível quando os dados ausentes são esparsos. Para fluxos de trabalho de aprendizado de máquina, consulte o capítulo Scale para normalizar recursos numéricos após a imputação.
Agrupando Dados
groupby() divide o DataFrame em grupos, aplica uma função a cada grupo e combina os resultados. É o equivalente pandas do GROUP BY em SQL.
import pandas as pd
data = {
'department': ['Eng', 'Eng', 'HR', 'HR', 'Eng'],
'name': ['Alice', 'Bob', 'Carol', 'Dave', 'Eve'],
'salary': [90000, 95000, 70000, 72000, 88000],
}
df = pd.DataFrame(data)
print(df.groupby('department')['salary'].mean())Saída:
department
Eng 91000.0
HR 71000.0
Name: salary, dtype: float64Aplique múltiplas funções de agregação de uma vez usando agg():
print(df.groupby('department')['salary'].agg(['mean', 'min', 'max', 'count']))Saída:
mean min max count
department
Eng 91000.0 88000 95000 3
HR 71000.0 70000 72000 2Mesclando e Concatenando DataFrames
Mesclando (como SQL JOIN)
Use pd.merge() para combinar dois DataFrames em uma coluna-chave compartilhada:
import pandas as pd
employees = pd.DataFrame({
'emp_id': [1, 2, 3],
'name': ['Alice', 'Bob', 'Carol'],
'dept_id': [10, 20, 10],
})
departments = pd.DataFrame({
'dept_id': [10, 20],
'dept_name': ['Engineering', 'HR'],
})
merged = pd.merge(employees, departments, on='dept_id')
print(merged)Saída:
emp_id name dept_id dept_name
0 1 Alice 10 Engineering
1 2 Bob 20 HR
2 3 Carol 10 EngineeringO padrão é um inner join (somente linhas com uma chave correspondente em ambos os DataFrames). Controle o tipo de junção com how:
how='left'— todas as linhas do DataFrame da esquerda, linhas correspondentes da direitahow='right'— todas as linhas do DataFrame da direita, linhas correspondentes da esquerdahow='outer'— todas as linhas de ambos os DataFrames;NaNonde não há correspondência
Concatenando (empilhando DataFrames)
Use pd.concat() para empilhar DataFrames com as mesmas colunas verticalmente:
import pandas as pd
q1 = pd.DataFrame({'name': ['Alice', 'Bob'], 'sales': [120, 95]})
q2 = pd.DataFrame({'name': ['Carol', 'Dave'], 'sales': [110, 130]})
combined = pd.concat([q1, q2], ignore_index=True)
print(combined)Saída:
name sales
0 Alice 120
1 Bob 95
2 Carol 110
3 Dave 130ignore_index=True reinicia o índice de linhas para que ele vá de 0 a 3, em vez de repetir 0 e 1 de cada DataFrame de origem.
Estatísticas Descritivas
O pandas facilita o cálculo de estatísticas resumidas em um DataFrame inteiro ou em colunas individuais:
import pandas as pd
data = {
'name': ['Alice', 'Bob', 'Carol', 'Dave'],
'age': [25, 30, 28, 35],
'score': [88.5, 92.0, 79.5, 95.0],
}
df = pd.DataFrame(data)
print(df[['age', 'score']].describe())Saída:
age score
count 4.000000 4.000000
mean 29.500000 88.750000
std 4.203173 6.714412
min 25.000000 79.500000
25% 27.250000 86.250000
50% 29.000000 90.250000
75% 31.250000 92.750000
max 35.000000 95.000000Estatísticas individuais também estão disponíveis como métodos diretos: df['score'].mean(), df['score'].std(), df['score'].median(), df['age'].max().
Visualização Básica de Dados
O pandas se integra ao Matplotlib para que você possa plotar diretamente a partir de um DataFrame com o método .plot(). Instale o Matplotlib primeiro, se ainda não o fez: pip install matplotlib.
Gráfico de linha
import pandas as pd
import matplotlib.pyplot as plt
data = {
'month': ['Jan', 'Feb', 'Mar', 'Apr', 'May'],
'revenue': [15000, 18000, 16500, 21000, 23000],
}
df = pd.DataFrame(data)
df.plot(kind='line', x='month', y='revenue', marker='o', title='Monthly Revenue')
plt.ylabel('Revenue ($)')
plt.tight_layout()
plt.show()Gráfico de barras
df.plot(kind='bar', x='month', y='revenue', color='steelblue', title='Monthly Revenue')
plt.ylabel('Revenue ($)')
plt.xticks(rotation=0)
plt.tight_layout()
plt.show()Valores comuns para o parâmetro kind:
kind | Tipo de gráfico |
|---|---|
'line' | Gráfico de linha |
'bar' | Gráfico de barras vertical |
'barh' | Gráfico de barras horizontal |
'hist' | Histograma |
'box' | Diagrama de caixa |
'scatter' | Gráfico de dispersão (requer x e y) |
'pie' | Gráfico de pizza |
Para plotagens mais avançadas, consulte os capítulos Matplotlib Introduction e Matplotlib Scatter Plot.
Armadilhas Comuns
SettingWithCopyWarning: quando você filtra um DataFrame e tenta modificar o resultado, o pandas pode avisar que você está modificando uma cópia em vez do original. Use .copy() para ser explícito:
# Safe: work on an explicit copy
young = df[df['age'] < 30].copy()
young['group'] = 'junior'Indexação encadeada: df['col'][0] = value pode ou não modificar o DataFrame original. Sempre use df.loc[0, 'col'] = value para atribuição.
Nomes de colunas com espaços: se uma coluna se chamar "first name", você deve usar a notação de colchetes — df['first name'] — e não a notação de ponto (df.first name é um erro de sintaxe).
Inteiro vs. float após fillna: preencher NaN em uma coluna de inteiros com um número promove a coluna para float64 porque NaN é um float. Use pd.Int64Dtype() (inteiro anulável) se precisar manter a semântica de inteiros com valores ausentes.
Capítulos Relacionados
- NumPy Tutorial — a biblioteca de arrays sobre a qual o pandas é construído
- Matplotlib Introduction — crie gráficos com qualidade de publicação a partir dos seus dados
- Matplotlib Scatter Plot — visualize relações entre duas variáveis numéricas
- Data Distribution — entenda como os valores estão distribuídos em um conjunto de dados
- Scale — normalize e padronize recursos numéricos antes da modelagem
- Categorical Data — codifique colunas não numéricas para aprendizado de máquina
- Train/Test Split — divida um DataFrame do pandas em conjuntos de treino e teste
- SciPy Tutorial — funções estatísticas e científicas que complementam o pandas