Pandas Cheat Sheet: Folha de Consulta
Última atualização
Criar um DataFrame
DataFrames pequenos montados à mão, para exemplos, testes e tabelas de consulta.
| Tarefa | Código |
|---|---|
| Importar pandas e NumPy | import pandas as pd
import numpy as np |
| A partir de um dict de colunas | df = pd.DataFrame({"name": ["Ada", "Ben"], "age": [36, 28]}) |
| A partir de uma lista de linhas | pd.DataFrame([{"name": "Ada", "age": 36}, {"name": "Ben", "age": 28}]) |
| A partir de um array NumPy | pd.DataFrame(np.arange(6).reshape(3, 2), columns=["x", "y"]) |
| Uma Series com rótulos | s = pd.Series([3, 5, 2], index=["a", "b", "c"]) |
| Um intervalo de datas | pd.date_range("2026-01-01", periods=7, freq="D") |
Ler e gravar arquivos
Uma chamada carrega um arquivo em um DataFrame, e outra grava de volta.
| Tarefa | Código |
|---|---|
| Ler um arquivo CSV | df = pd.read_csv("sales.csv") |
| Só algumas colunas, com datas de verdade | pd.read_csv("sales.csv", usecols=["date", "city", "sales"], parse_dates=["date"]) |
| Usar uma coluna como índice | pd.read_csv("sales.csv", index_col="id") |
| Tab ou outro separador | pd.read_csv("sales.tsv", sep="\t") |
| Tratar outros marcadores como ausentes | pd.read_csv("sales.csv", na_values=["n/a", "-"]) |
| Ler só as primeiras linhas | pd.read_csv("sales.csv", nrows=1000) |
| Ler uma planilha Excel (requer openpyxl) | pd.read_excel("report.xlsx", sheet_name="2026") |
| Ler registros JSON | pd.read_json("records.json") |
| Ler de um banco SQL | pd.read_sql("SELECT * FROM orders", conn) |
| Gravar CSV sem o índice | df.to_csv("clean.csv", index=False) |
| Gravar Excel ou Parquet | df.to_excel("clean.xlsx", index=False), df.to_parquet("clean.parquet") |
Inspecionar os dados
As primeiras chamadas a fazer em qualquer dataset novo.
| Tarefa | Código |
|---|---|
| Primeiras e últimas linhas | df.head(), df.tail(3) |
| Número de linhas e colunas | df.shape # (6, 7) |
| Tipos e contagem de não nulos | df.info() |
| Estatísticas das colunas numéricas | df.describe() |
| Resumo de todas as colunas | df.describe(include="all") |
| Nomes e tipos das colunas | df.columns, df.dtypes |
| Contar cada valor | df["city"].value_counts() |
| Proporção de cada valor | df["city"].value_counts(normalize=True) |
| Valores distintos e quantos são | df["city"].unique(), df["city"].nunique() |
| Valores ausentes por coluna | df.isna().sum() |
| Amostra aleatória de linhas | df.sample(3, random_state=0) |
| Correlação das colunas numéricas | df.corr(numeric_only=True) |
Selecionar colunas e linhas
loc seleciona por rótulo e inclui o fim da fatia. iloc seleciona por posição e exclui o fim.
| Tarefa | Código |
|---|---|
| Uma coluna, como Series | df["age"] |
| Várias colunas, como DataFrame | df[["name", "age"]] |
| Linhas e colunas por rótulo | df.loc[0:2, ["name", "age"]] |
| Linhas e colunas por posição | df.iloc[0:2, 0:3] |
| Um único valor | df.at[0, "age"], df.iat[0, 3] |
| Última linha | df.iloc[-1] |
| Colunas de um tipo | df.select_dtypes(include="number") |
| Colunas de texto (pandas 3) | df.select_dtypes(include="str") |
| Colunas pelo nome | df.filter(like="sal"), df.filter(regex="^(age|salary)$") |
| Buscar linhas por uma coluna | df.set_index("name").loc["Ada", "salary"] |
| Voltar a um índice 0, 1, 2 | df.reset_index(drop=True) |
| Remover colunas ou linhas | df.drop(columns=["email"]), df.drop(index=[0, 1]) |
Filtrar linhas
Coloque cada condição entre parênteses e combine com & (e), | (ou) e ~ (não).
| Tarefa | Código |
|---|---|
| Linhas que atendem a uma condição | df[df["age"] > 30] |
| As duas condições | df[(df["age"] > 30) & (df["city"] == "Oslo")] |
| Qualquer uma das condições | df[(df["city"] == "Oslo") | (df["salary"] > 6000)] |
| Valor em uma lista | df[df["city"].isin(["Oslo", "Rome"])] |
| Valor fora de uma lista | df[~df["city"].isin(["Oslo", "Rome"])] |
| Entre dois valores, extremos inclusos | df[df["age"].between(30, 40)] |
| Filtrar com uma string de query | df.query("age > 30 and city == 'Oslo'") |
| Usar uma variável na query | min_age = 30
df.query("age > @min_age") |
| Texto contém | df[df["name"].str.contains("e", case=False)] |
| Valores ausentes ou presentes | df[df["age"].isna()], df[df["age"].notna()] |
| Filtrar linhas e escolher colunas | df.loc[df["age"] > 30, ["name", "salary"]] |
| As n maiores ou menores linhas | df.nlargest(3, "salary"), df.nsmallest(2, "age") |
| Linhas com valor repetido | df[df.duplicated(subset=["city"], keep=False)] |
Ordenar e ranquear
| Tarefa | Código |
|---|---|
| Ordenar por uma coluna | df.sort_values("salary") |
| Maiores primeiro | df.sort_values("salary", ascending=False) |
| Ordenar por várias colunas | df.sort_values(["city", "salary"], ascending=[True, False]) |
| Valores ausentes primeiro | df.sort_values("age", na_position="first") |
| Ordenar pelo índice | df.sort_index() |
| Ranquear valores, 1 é o maior | df["salary"].rank(ascending=False) |
Adicionar e alterar colunas
Operações na coluna inteira são rápidas. Use apply só quando nenhum método nativo resolver.
| Tarefa | Código |
|---|---|
| Nova coluna a partir de outras | df["bonus"] = df["salary"] * 0.1 |
| Adicionar coluna dentro de uma cadeia | df.assign(bonus=lambda d: d["salary"] * 0.1) |
| Valor a partir de uma condição | df["level"] = np.where(df["age"] >= 40, "senior", "junior") |
| Valor a partir de várias condições | df["band"] = np.select([df["age"] < 30, df["age"] < 45], ["young", "mid"], default="senior") |
| Alterar valores onde a condição vale | df.loc[df["city"] == "Lima", "salary"] = 4000 |
| Mapear valores com um dict | df["country"] = df["city"].map({"Oslo": "NO", "Rome": "IT", "Lima": "PE"}) |
| Aplicar uma função a uma coluna | df["salary"].apply(lambda x: round(x, -3)) |
| Aplicar uma função a cada célula | df[["age", "salary"]].map(lambda x: x / 1000) |
| Renomear colunas | df.rename(columns={"salary": "pay"}) |
| Mudar o tipo de uma coluna | df["salary"].astype("float64") |
| Texto para número, inválidos viram NaN | pd.to_numeric(s, errors="coerce") |
| Números em faixas com rótulo | pd.cut(df["age"], bins=[0, 30, 45, 120], labels=["young", "mid", "senior"]) |
| Números em grupos de mesmo tamanho | pd.qcut(df["salary"], q=4, labels=False) |
| Percorrer linhas (lento, último recurso) | for row in df.itertuples():
print(row.name, row.salary) |
Valores ausentes e limpeza
Números ausentes aparecem como NaN, datas ausentes como NaT. Cada uma destas chamadas devolve um objeto novo, então atribua o resultado.
| Tarefa | Código |
|---|---|
| Proporção de ausentes por coluna | df.isna().mean() |
| Remover linhas com algum ausente | df.dropna() |
| Remover linhas sem uma coluna-chave | df.dropna(subset=["age"]) |
| Preencher com um valor por coluna | df.fillna({"age": df["age"].median()}) |
| Preencher com a linha anterior ou seguinte | df["age"].ffill(), df["age"].bfill() |
| Preencher lacunas por interpolação | df["age"].interpolate() |
| Transformar marcadores em ausentes | df.replace(["n/a", "-", ""], np.nan) |
| Remover linhas duplicadas | df.drop_duplicates() |
| Manter a última linha por chave | df.drop_duplicates(subset=["city"], keep="last") |
| Arrumar nomes de colunas | df.columns = df.columns.str.strip().str.lower().str.replace(" ", "_") |
| Limitar valores extremos | df["salary"].clip(lower=4000, upper=6000) |
| Tipo category para texto repetido | df["city"] = df["city"].astype("category") |
Colunas de texto (.str)
No pandas 3, colunas de texto recebem o dtype str por padrão. Os métodos .str funcionam na coluna inteira, e valores ausentes continuam ausentes.
| Tarefa | Código |
|---|---|
| Maiúsculas, minúsculas ou título | df["name"].str.upper(), df["name"].str.lower(), df["name"].str.title() |
| Remover espaços | df["name"].str.strip() |
| Substituir texto | df["email"].str.replace("mail.com", "example.com") |
| Substituir com regex | df["email"].str.replace(r"@.*", "", regex=True) |
| Contém, começa com | df["name"].str.contains("a"), df["name"].str.startswith("E") |
| Tamanho de cada valor | df["name"].str.len() |
| Primeiros caracteres | df["name"].str[:2] |
| Dividir em colunas | df["email"].str.split("@", expand=True) |
| Extrair com grupo de regex | df["email"].str.extract(r"@(\w+)") |
| Juntar colunas de texto | df["name"] + " (" + df["city"] + ")" |
| Completar números com zeros | df["salary"].astype("str").str.zfill(6) |
| O novo dtype de texto | df["name"].dtype # str |
Datas e horas
O acessor .dt funciona em colunas datetime. Um índice de datas ordenado (ts abaixo) permite fatiar por texto e fazer resampling.
| Tarefa | Código |
|---|---|
| Converter coluna para datetime | df["date"] = pd.to_datetime(df["date"]) |
| Converter com formato exato | pd.to_datetime(["03/01/2026", "15/01/2026"], format="%d/%m/%Y") |
| Ano, mês, nome do dia da semana | df["date"].dt.year, df["date"].dt.month, df["date"].dt.day_name() |
| Agrupar datas por mês | df["date"].dt.to_period("M") |
| Dias entre duas datas | (pd.Timestamp("2026-12-31") - df["date"]).dt.days |
| Somar dias ou meses | df["date"] + pd.Timedelta(days=30), df["date"] + pd.DateOffset(months=1) |
| Linhas em um intervalo de datas | df[df["date"].between("2021-01-01", "2022-12-31")] |
| Índice de datas, fatiado por texto | ts = df.set_index("date").sort_index()
ts.loc["2021":"2022"] |
| Total por mês | ts["salary"].resample("ME").sum() |
Média semanal; "QE" é trimestral, "YE" anual | ts["salary"].resample("W").mean() |
| Média móvel | ts["salary"].rolling(3).mean() |
| Variação em relação à linha anterior | ts["salary"].diff(), ts["salary"].pct_change() |
| Deslocar valores uma linha para baixo | ts["salary"].shift(1) |
| Total acumulado | ts["salary"].cumsum() |
| Definir e converter fusos horários | ts.index.tz_localize("UTC").tz_convert("Europe/Oslo") |
Agrupar e agregar
groupby divide as linhas por chave, aplica uma função a cada grupo e combina os resultados.
| Tarefa | Código |
|---|---|
| Média por grupo | df.groupby("city")["salary"].mean() |
| Várias estatísticas de uma vez | df.groupby("city")["salary"].agg(["mean", "max", "count"]) |
| Colunas de resultado com nome | df.groupby("city").agg(avg_pay=("salary", "mean"), people=("name", "count")) |
| Agrupar por duas colunas | df.groupby(["city", "team"])["salary"].sum() |
| Manter as chaves como colunas | df.groupby("city", as_index=False)["salary"].mean() |
| Número de linhas por grupo | df.groupby("city").size() |
| Resultado do grupo em cada linha | df["city_avg"] = df.groupby("city")["salary"].transform("mean") |
| Manter só alguns grupos | df.groupby("city").filter(lambda g: len(g) >= 2) |
| Linha com o máximo de cada grupo | df.loc[df.groupby("city")["salary"].idxmax()] |
| As n maiores linhas por grupo | df.sort_values("salary", ascending=False).groupby("city").head(2) |
| Numerar as linhas de cada grupo | df.groupby("city").cumcount() |
| Percorrer os grupos | for city, group in df.groupby("city"):
print(city, len(group)) |
| Filtrar, agrupar e ordenar numa cadeia | (df.query("age > 30")
.groupby("city", as_index=False)
.agg(avg_pay=("salary", "mean"))
.sort_values("avg_pay", ascending=False)) |
Pivotar e remodelar
Dados longos têm uma linha por observação. Dados largos espalham uma variável por várias colunas.
| Tarefa | Código |
|---|---|
| Tabela dinâmica | df.pivot_table(index="city", columns="team", values="salary", aggfunc="mean", fill_value=0) |
| Tabela dinâmica com totais | df.pivot_table(index="city", values="salary", aggfunc="sum", margins=True) |
| Contar combinações | pd.crosstab(df["city"], df["team"]) |
| Proporções por linha | pd.crosstab(df["city"], df["team"], normalize="index") |
| De largo para longo | long = df.melt(id_vars="name", value_vars=["age", "salary"], var_name="field", value_name="value") |
| De longo para largo | long.pivot(index="name", columns="field", values="value") |
| Nível interno do índice para colunas | df.groupby(["city", "team"])["salary"].sum().unstack(fill_value=0) |
| Uma linha por item da lista | pd.DataFrame({"id": [1, 2], "tags": [["a", "b"], ["c"]]}).explode("tags") |
| One-hot encoding de uma coluna | pd.get_dummies(df["team"], prefix="team") |
| Trocar linhas e colunas | df.T |
Combinar DataFrames
concat empilha frames, merge junta por colunas-chave como um join de SQL.
| Tarefa | Código |
|---|---|
| Empilhar linhas | pd.concat([df_2025, df_2026], ignore_index=True) |
| Colocar lado a lado | pd.concat([left, right], axis=1) |
| Juntar por uma coluna-chave | orders.merge(customers, on="customer_id", how="left") |
| Tipos de join | how="inner", "left", "right", "outer" |
| Chaves com nomes diferentes | orders.merge(users, left_on="customer_id", right_on="id") |
| Validar o join e marcar a origem de cada linha | orders.merge(customers, on="customer_id", how="left", validate="many_to_one", indicator=True) |
| Juntar pelo índice | left.join(right, how="inner") |
| Linhas sem correspondência na outra tabela | orders[~orders["customer_id"].isin(customers["customer_id"])] |
Gráficos com pandas
O pandas desenha com Matplotlib. Toda chamada de plot devolve um ax do Matplotlib, então você pode continuar estilizando.
| Tarefa | Código |
|---|---|
| Gráfico de linha de uma série | ts["salary"].plot() |
| Gráfico de linha com duas colunas | df.plot(x="date", y="salary") |
| Gráfico de barras de um resumo | df.groupby("city")["salary"].mean().plot.bar() |
| Barras horizontais ordenadas | df["city"].value_counts().sort_values().plot.barh() |
| Histograma | df["salary"].plot.hist(bins=20) |
| Gráfico de dispersão | df.plot.scatter(x="age", y="salary") |
| Boxplot por grupo | df.boxplot(column="salary", by="city") |
| Título e rótulo do eixo | ax = df.plot(x="date", y="salary", title="Salary")
ax.set_ylabel("EUR") |
| Mostrar ou salvar o gráfico | plt.show(), ax.figure.savefig("salary.png", dpi=150) |
pandas 3: formas antigas e o que escrever agora
Código copiado de tutoriais antigos costuma falhar ou gerar avisos no pandas 3. Use as formas da coluna pandas 3.
| Tarefa | pandas 3 | Forma antiga |
|---|---|---|
| Função em cada célula | df.map(f) | df.applymap(f) |
| Preencher com a linha anterior | df.ffill() | df.fillna(method="ffill") |
| Adicionar linhas | pd.concat([df, new_rows]) | df.append(new_rows) |
| Resampling no fim do mês | ts["salary"].resample("ME").sum() | resample("M") |
| Datas por hora | pd.date_range("2026-01-01", periods=24, freq="h") | freq="H" |
| Definir um valor | df.loc[0, "age"] = 37 | df["age"][0] = 37 |
| Alterar um subconjunto filtrado | high = df[df["salary"] > 5000]
high["salary"] = 0 | high = df[df["salary"] > 5000].copy() |
| É uma coluna de texto? | df["name"].dtype == "str" | df["name"].dtype == object |
O código pandas que um analista de dados usa todo dia, organizado por tarefa: criar e carregar dados, inspecionar, selecionar e filtrar linhas, adicionar colunas, tratar valores ausentes, trabalhar com texto e datas, agrupar e agregar, remodelar, juntar e plotar. Cada linha traz um trecho curto para colar e uma frase sobre o que ele faz.
Tudo aqui foi escrito para o pandas 3, a versão que a Coddy roda: colunas de texto usam o novo dtype str, o Copy-on-Write está sempre ativo, e APIs removidas como applymap e fillna(method=...) aparecem só na tabela de formas antigas. Os exemplos usam um DataFrame df com as colunas name, city, team, age, salary, date e email. Está começando em Python? Comece pela folha de consulta Python e pelo playground de Python, e deixe as folhas de consulta de NumPy, Matplotlib e scikit-learn abertas ao lado desta.
Perguntas frequentes sobre a folha de consulta pandas
Esta folha de consulta de pandas é grátis?
Qual versão do pandas esta folha de consulta cobre?
str, o Copy-on-Write está sempre ativo, e chamadas removidas no pandas 3 (applymap, fillna(method=...), append, os aliases de frequência M e H) aparecem só na última tabela, ao lado do que escrever no lugar. Quase todos os trechos também rodam no pandas 2.2, exceto as linhas que dependem do dtype str ou do Copy-on-Write.Qual é a diferença entre loc e iloc?
loc seleciona por rótulo, ou seja, pelos valores do índice e nomes das colunas, e uma fatia como df.loc[0:2] inclui o fim. iloc seleciona por posição inteira, como uma lista Python, então df.iloc[0:2] devolve as duas primeiras linhas e exclui o fim. Use loc com uma condição para filtrar linhas e escolher colunas de uma vez: df.loc[df["age"] > 30, ["name"]].Como filtro um DataFrame com várias condições?
& para e, | para ou e ~ para não: df[(df["age"] > 30) & (df["city"] == "Oslo")]. O and e o or do Python não funcionam em colunas inteiras. Para filtros longos, df.query("age > 30 and city == 'Oslo'") é mais fácil de ler.Qual é a diferença entre merge, join e concat?
merge combina dois DataFrames por colunas-chave, como um join de SQL, com how="inner", "left", "right" ou "outer". join é um atalho que faz o merge pelo índice. concat não compara chaves: ele empilha os frames um sobre o outro, ou lado a lado com axis=1.Por que minha atribuição não altera o DataFrame?
df["age"][0] = 37 altera um objeto temporário e deixa o df intacto. Escreva tudo em uma chamada loc: df.loc[0, "age"] = 37. Métodos como dropna e fillna também devolvem um objeto novo, então atribua o resultado.