Uma tabela de colunas rotuladas
Um DataFrame é uma tabela bidimensional: um conjunto de colunas, cada uma uma Series, que compartilham um índice de rótulos de linha. É o cavalo de batalha da análise de dados de mercado: uma linha por símbolo ou por dia, uma coluna por campo (preço, volume, retorno). Constrói-se a partir de um dicionário de colunas, pd.DataFrame({"price": [...], "volume": [...]}, index=symbols), ou de uma lista de dicionários de linhas. Cada coluna tem seu próprio dtype (preços são float64, volumes int64), ao contrário de um array NumPy, que tem um único dtype para tudo.
import pandas as pd
df = pd.DataFrame(
{"price": [184.25, 410.2, 171.0], "volume": [200, 50, 300]},
index=["AAPL", "MSFT", "GOOG"],
)
print(df)
# price volume
# AAPL 184.25 200
# MSFT 410.20 50
# GOOG 171.00 300
print(df.shape, df.columns.tolist()) # (3, 2) ['price', 'volume']
print(df.dtypes.astype(str).to_dict()) # {'price': 'float64', 'volume': 'int64'}
rows = [{"symbol": "AAPL", "price": 184.25}, {"symbol": "MSFT", "price": 410.2}]
print(pd.DataFrame(rows)) # from a list of row dictionaries
# symbol price
# 0 AAPL 184.25
# 1 MSFT 410.20Colunas, novas colunas e linhas filtradas
df["price"] é uma coluna, uma Series; df[["price"]] com uma lista é um DataFrame de uma coluna. Uma coluna nova vem de aritmética entre colunas: df.assign(notional=df["price"] * df["volume"]) devolve um quadro novo com a coluna extra e deixa df intacto (escrever df["notional"] = ... altera o próprio df). Uma condição booleana sobre uma coluna filtra linhas, df[df["volume"] >= 100], e df.sort_values("volume", ascending=False) as ordena, com .head(n) ficando com as primeiras n. Tudo isso opera sobre colunas inteiras de uma vez: nunca percorra linhas com iterrows() quando existe uma operação de coluna.
import pandas as pd
df = pd.DataFrame(
{"price": [184.25, 410.2, 171.0], "volume": [200, 50, 300]},
index=["AAPL", "MSFT", "GOOG"],
)
bigger = df.assign(notional=df["price"] * df["volume"]) # a new frame
print(bigger)
# price volume notional
# AAPL 184.25 200 36850.0
# MSFT 410.20 50 20510.0
# GOOG 171.00 300 51300.0
print(df.columns.tolist()) # ['price', 'volume'] df is unchanged
print(df[df["volume"] >= 100]) # rows that pass the test
# price volume
# AAPL 184.25 200
# GOOG 171.00 300
print(df.sort_values("volume", ascending=False).head(2)) # the two biggest volumes
# price volume
# GOOG 171.00 300
# AAPL 184.25 200Resumos e uma olhada nos dados
Olhe sempre para uma tabela antes de confiar nela. df.head() mostra as primeiras linhas, df.shape dá (linhas, colunas), df.dtypes lista o tipo de cada coluna, df.isna().sum() conta os valores ausentes por coluna e df.describe() resume as colunas numéricas (contagem, média, desvio padrão, mínimo, quartis, máximo). Métodos de coluna como df.mean() dão um valor por coluna; df.sum(axis=1) dá um por linha. Um dtype object ou str onde você esperava números geralmente significa que texto entrou na coluna.
import pandas as pd
df = pd.DataFrame(
{"price": [184.25, 410.2, 171.0], "volume": [200, 50, 300]},
index=["AAPL", "MSFT", "GOOG"],
)
print(df.describe().loc[["count", "mean", "max"]])
# price volume
# count 3.00 3.000000
# mean 255.15 183.333333
# max 410.20 300.000000
print(df.mean().to_dict()) # {'price': 255.15, 'volume': 183.33333333333334}
print(df.sum(axis=1).tolist()) # [384.25, 460.2, 471.0] one value per row
print(df.isna().sum().to_dict()) # {'price': 0, 'volume': 0}
# Changing a copy never changes the original (pandas 3 copies on write)
cheap = df[df["price"] < 200].copy()
cheap.loc["AAPL", "price"] = 0.0
print(df.loc["AAPL", "price"]) # 184.25import pandas as pd
rows = [
{"symbol": "AAPL", "price": 184.25, "volume": 200},
{"symbol": "MSFT", "price": 410.2, "volume": 50},
]
df = pd.DataFrame(rows).set_index("symbol") # make a column the row labels
print(df)
# price volume
# symbol
# AAPL 184.25 200
# MSFT 410.20 50
print(df.rename(columns={"price": "px"}).columns.tolist()) # ['px', 'volume']
print(df.drop(columns="volume").columns.tolist()) # ['price']
print(df.reset_index().columns.tolist()) # ['symbol', 'price', 'volume']assign, filtragem booleana e sort_values, que devolvem quadros novos. O bug clássico é escrever uma coluna nova no argumento, o que a adiciona em silêncio à tabela de quem chama. Os testes do lab comparam o argumento antes e depois justamente por isso.pd.DataFrame({coluna: valores}, index=labels);df["c"]é uma Series,df[["c"]]um DataFrame; cada coluna tem seu dtype.assignadiciona uma coluna a um quadro novo;df[máscara]filtra linhas;sort_values(...).head(n)pega os n primeiros.- Olhe primeiro:
shape,dtypes,head(),describe(),isna().sum(); nunca edite o quadro de quem chama.
A seguir: selecionar dados com loc e iloc, as duas formas precisas de escolher linhas e colunas por rótulo ou por posição.
Lab: o que é avaliado
- Montar uma tabela de preços e volumes com
make_frame25 pts - Adicionar uma coluna de valor negociado com
add_notional25 pts - Manter só as linhas líquidas com
filter_liquid25 pts - Classificar as linhas por qualquer coluna com
top_by25 pts