Menu
CoddyTech

Hoja de Trucos de pandas

Última actualización

Crear un DataFrame

DataFrames pequeños creados a mano, para ejemplos, tests y tablas de consulta.

TareaCódigo
Importar pandas y NumPyimport pandas as pd import numpy as np
Desde un dict de columnasdf = pd.DataFrame({"name": ["Ada", "Ben"], "age": [36, 28]})
Desde una lista de filaspd.DataFrame([{"name": "Ada", "age": 36}, {"name": "Ben", "age": 28}])
Desde un array de NumPypd.DataFrame(np.arange(6).reshape(3, 2), columns=["x", "y"])
Una Series con etiquetass = pd.Series([3, 5, 2], index=["a", "b", "c"])
Un rango de fechaspd.date_range("2026-01-01", periods=7, freq="D")

Leer y escribir archivos

Una llamada carga un archivo en un DataFrame y otra lo vuelve a escribir.

TareaCódigo
Leer un archivo CSVdf = pd.read_csv("sales.csv")
Solo algunas columnas, con fechas realespd.read_csv("sales.csv", usecols=["date", "city", "sales"], parse_dates=["date"])
Usar una columna como índicepd.read_csv("sales.csv", index_col="id")
Tabulador u otro separadorpd.read_csv("sales.tsv", sep="\t")
Tratar otros marcadores como faltantespd.read_csv("sales.csv", na_values=["n/a", "-"])
Leer solo las primeras filaspd.read_csv("sales.csv", nrows=1000)
Leer una hoja de Excel (requiere openpyxl)pd.read_excel("report.xlsx", sheet_name="2026")
Leer registros JSONpd.read_json("records.json")
Leer de una base de datos SQLpd.read_sql("SELECT * FROM orders", conn)
Guardar un CSV sin el índicedf.to_csv("clean.csv", index=False)
Guardar en Excel o Parquetdf.to_excel("clean.xlsx", index=False), df.to_parquet("clean.parquet")

Inspeccionar los datos

Las primeras llamadas que conviene hacer con cualquier dataset nuevo.

TareaCódigo
Primeras y últimas filasdf.head(), df.tail(3)
Número de filas y columnasdf.shape # (6, 7)
Tipos de columna y conteo de no nulosdf.info()
Estadísticas de las columnas numéricasdf.describe()
Resumen de todas las columnasdf.describe(include="all")
Nombres y tipos de columnadf.columns, df.dtypes
Contar cada valordf["city"].value_counts()
Proporción de cada valordf["city"].value_counts(normalize=True)
Valores distintos y cuántos haydf["city"].unique(), df["city"].nunique()
Valores faltantes por columnadf.isna().sum()
Muestra aleatoria de filasdf.sample(3, random_state=0)
Correlación de columnas numéricasdf.corr(numeric_only=True)

Seleccionar columnas y filas

loc selecciona por etiqueta e incluye el final del slice. iloc selecciona por posición y lo excluye.

TareaCódigo
Una columna, como Seriesdf["age"]
Varias columnas, como DataFramedf[["name", "age"]]
Filas y columnas por etiquetadf.loc[0:2, ["name", "age"]]
Filas y columnas por posicióndf.iloc[0:2, 0:3]
Un solo valordf.at[0, "age"], df.iat[0, 3]
Última filadf.iloc[-1]
Columnas de un tipodf.select_dtypes(include="number")
Columnas de texto (pandas 3)df.select_dtypes(include="str")
Columnas por coincidencia de nombredf.filter(like="sal"), df.filter(regex="^(age|salary)$")
Buscar filas por una columnadf.set_index("name").loc["Ada", "salary"]
Volver a un índice 0, 1, 2df.reset_index(drop=True)
Eliminar columnas o filasdf.drop(columns=["email"]), df.drop(index=[0, 1])

Filtrar filas

Pon cada condición entre paréntesis y combínalas con & (y), | (o) y ~ (no).

TareaCódigo
Filas que cumplen una condicióndf[df["age"] > 30]
Ambas condicionesdf[(df["age"] > 30) & (df["city"] == "Oslo")]
Cualquiera de las dosdf[(df["city"] == "Oslo") | (df["salary"] > 6000)]
Valor en una listadf[df["city"].isin(["Oslo", "Rome"])]
Valor fuera de una listadf[~df["city"].isin(["Oslo", "Rome"])]
Entre dos valores, extremos incluidosdf[df["age"].between(30, 40)]
Filtrar con una querydf.query("age > 30 and city == 'Oslo'")
Usar una variable en una querymin_age = 30 df.query("age > @min_age")
El texto contienedf[df["name"].str.contains("e", case=False)]
Valores faltantes o presentesdf[df["age"].isna()], df[df["age"].notna()]
Filtrar filas y elegir columnasdf.loc[df["age"] > 30, ["name", "salary"]]
Las n filas mayores o menoresdf.nlargest(3, "salary"), df.nsmallest(2, "age")
Filas con un valor repetidodf[df.duplicated(subset=["city"], keep=False)]

Ordenar y rankear

TareaCódigo
Ordenar por una columnadf.sort_values("salary")
De mayor a menordf.sort_values("salary", ascending=False)
Ordenar por varias columnasdf.sort_values(["city", "salary"], ascending=[True, False])
Faltantes primerodf.sort_values("age", na_position="first")
Ordenar por el índicedf.sort_index()
Rankear valores, 1 es el más altodf["salary"].rank(ascending=False)

Añadir y modificar columnas

Las operaciones sobre columnas completas son rápidas. Recurre a apply solo cuando ningún método integrado sirva.

TareaCódigo
Columna nueva a partir de otrasdf["bonus"] = df["salary"] * 0.1
Añadir una columna dentro de una cadenadf.assign(bonus=lambda d: d["salary"] * 0.1)
Valor según una condicióndf["level"] = np.where(df["age"] >= 40, "senior", "junior")
Valor según varias condicionesdf["band"] = np.select([df["age"] < 30, df["age"] < 45], ["young", "mid"], default="senior")
Cambiar valores donde se cumple una condicióndf.loc[df["city"] == "Lima", "salary"] = 4000
Mapear valores con un dictdf["country"] = df["city"].map({"Oslo": "NO", "Rome": "IT", "Lima": "PE"})
Aplicar una función a una columnadf["salary"].apply(lambda x: round(x, -3))
Aplicar una función a cada celdadf[["age", "salary"]].map(lambda x: x / 1000)
Renombrar columnasdf.rename(columns={"salary": "pay"})
Cambiar el tipo de una columnadf["salary"].astype("float64")
Texto a números, valores inválidos a NaNpd.to_numeric(s, errors="coerce")
Números en intervalos con etiquetapd.cut(df["age"], bins=[0, 30, 45, 120], labels=["young", "mid", "senior"])
Números en grupos del mismo tamañopd.qcut(df["salary"], q=4, labels=False)
Recorrer filas (lento, último recurso)for row in df.itertuples(): print(row.name, row.salary)

Valores faltantes y limpieza

Los números faltantes se muestran como NaN y las fechas faltantes como NaT. Cada una de estas llamadas devuelve un objeto nuevo, así que asigna el resultado.

TareaCódigo
Proporción de faltantes por columnadf.isna().mean()
Eliminar filas con algún faltantedf.dropna()
Eliminar filas sin una columna clavedf.dropna(subset=["age"])
Rellenar con un valor por columnadf.fillna({"age": df["age"].median()})
Rellenar con la fila anterior o siguientedf["age"].ffill(), df["age"].bfill()
Rellenar huecos por interpolacióndf["age"].interpolate()
Convertir marcadores en faltantesdf.replace(["n/a", "-", ""], np.nan)
Eliminar filas duplicadasdf.drop_duplicates()
Quedarse con la última fila por clavedf.drop_duplicates(subset=["city"], keep="last")
Limpiar nombres de columnadf.columns = df.columns.str.strip().str.lower().str.replace(" ", "_")
Recortar valores extremosdf["salary"].clip(lower=4000, upper=6000)
Tipo category para texto repetidodf["city"] = df["city"].astype("category")

Columnas de texto (.str)

En pandas 3 las columnas de texto reciben el dtype str por defecto. Los métodos .str trabajan sobre toda la columna y los valores faltantes siguen siendo faltantes.

TareaCódigo
Mayúsculas, minúsculas o tipo títulodf["name"].str.upper(), df["name"].str.lower(), df["name"].str.title()
Quitar espaciosdf["name"].str.strip()
Reemplazar textodf["email"].str.replace("mail.com", "example.com")
Reemplazar con una regexdf["email"].str.replace(r"@.*", "", regex=True)
Contiene, empieza pordf["name"].str.contains("a"), df["name"].str.startswith("E")
Longitud de cada valordf["name"].str.len()
Primeros caracteresdf["name"].str[:2]
Separar en columnasdf["email"].str.split("@", expand=True)
Extraer con un grupo de regexdf["email"].str.extract(r"@(\w+)")
Unir columnas de textodf["name"] + " (" + df["city"] + ")"
Rellenar números con cerosdf["salary"].astype("str").str.zfill(6)
El nuevo dtype de textodf["name"].dtype # str

Fechas y horas

El accesor .dt funciona con columnas datetime. Un índice de fechas ordenado (ts abajo) permite hacer slicing con texto y remuestrear.

TareaCódigo
Convertir una columna a datetimedf["date"] = pd.to_datetime(df["date"])
Convertir con un formato exactopd.to_datetime(["03/01/2026", "15/01/2026"], format="%d/%m/%Y")
Año, mes, nombre del díadf["date"].dt.year, df["date"].dt.month, df["date"].dt.day_name()
Agrupar fechas por mesdf["date"].dt.to_period("M")
Días entre dos fechas(pd.Timestamp("2026-12-31") - df["date"]).dt.days
Sumar días o mesesdf["date"] + pd.Timedelta(days=30), df["date"] + pd.DateOffset(months=1)
Filas en un rango de fechasdf[df["date"].between("2021-01-01", "2022-12-31")]
Índice de fechas, slicing con textots = df.set_index("date").sort_index() ts.loc["2021":"2022"]
Total por mests["salary"].resample("ME").sum()
Media semanal; "QE" es trimestral, "YE" anualts["salary"].resample("W").mean()
Media móvilts["salary"].rolling(3).mean()
Cambio respecto a la fila anteriorts["salary"].diff(), ts["salary"].pct_change()
Desplazar valores una fila abajots["salary"].shift(1)
Total acumuladots["salary"].cumsum()
Asignar y convertir zonas horariasts.index.tz_localize("UTC").tz_convert("Europe/Oslo")

Agrupar y agregar

groupby divide las filas por clave, aplica una función a cada grupo y combina los resultados.

TareaCódigo
Media por grupodf.groupby("city")["salary"].mean()
Varias estadísticas a la vezdf.groupby("city")["salary"].agg(["mean", "max", "count"])
Columnas de resultado con nombredf.groupby("city").agg(avg_pay=("salary", "mean"), people=("name", "count"))
Agrupar por dos columnasdf.groupby(["city", "team"])["salary"].sum()
Mantener las claves como columnasdf.groupby("city", as_index=False)["salary"].mean()
Número de filas por grupodf.groupby("city").size()
Resultado del grupo en cada filadf["city_avg"] = df.groupby("city")["salary"].transform("mean")
Quedarse solo con algunos gruposdf.groupby("city").filter(lambda g: len(g) >= 2)
Fila con el máximo por grupodf.loc[df.groupby("city")["salary"].idxmax()]
Las n primeras filas por grupodf.sort_values("salary", ascending=False).groupby("city").head(2)
Numerar las filas de cada grupodf.groupby("city").cumcount()
Recorrer los gruposfor city, group in df.groupby("city"): print(city, len(group))
Filtrar, agrupar y ordenar en una cadena(df.query("age > 30") .groupby("city", as_index=False) .agg(avg_pay=("salary", "mean")) .sort_values("avg_pay", ascending=False))

Pivotar y reorganizar

Los datos en formato largo tienen una fila por observación. Los datos en formato ancho reparten una variable entre varias columnas.

TareaCódigo
Tabla dinámicadf.pivot_table(index="city", columns="team", values="salary", aggfunc="mean", fill_value=0)
Tabla dinámica con totalesdf.pivot_table(index="city", values="salary", aggfunc="sum", margins=True)
Contar combinacionespd.crosstab(df["city"], df["team"])
Proporciones por filapd.crosstab(df["city"], df["team"], normalize="index")
De ancho a largolong = df.melt(id_vars="name", value_vars=["age", "salary"], var_name="field", value_name="value")
De largo a ancholong.pivot(index="name", columns="field", values="value")
Nivel interno del índice a columnasdf.groupby(["city", "team"])["salary"].sum().unstack(fill_value=0)
Una fila por elemento de listapd.DataFrame({"id": [1, 2], "tags": [["a", "b"], ["c"]]}).explode("tags")
One-hot encoding de una columnapd.get_dummies(df["team"], prefix="team")
Intercambiar filas y columnasdf.T

Combinar DataFrames

concat apila DataFrames y merge los une por columnas clave, igual que en SQL.

TareaCódigo
Apilar filaspd.concat([df_2025, df_2026], ignore_index=True)
Poner lado a ladopd.concat([left, right], axis=1)
Unir por una columna claveorders.merge(customers, on="customer_id", how="left")
Tipos de joinhow="inner", "left", "right", "outer"
Claves con nombres distintosorders.merge(users, left_on="customer_id", right_on="id")
Validar el join y marcar el origen de cada filaorders.merge(customers, on="customer_id", how="left", validate="many_to_one", indicator=True)
Unir por el índiceleft.join(right, how="inner")
Filas sin coincidencia en otra tablaorders[~orders["customer_id"].isin(customers["customer_id"])]

Graficar con pandas

pandas dibuja con Matplotlib. Cada llamada de gráfico devuelve un ax de Matplotlib, así que puedes seguir dándole estilo.

TareaCódigo
Gráfico de líneas de una seriets["salary"].plot()
Gráfico de líneas con dos columnasdf.plot(x="date", y="salary")
Gráfico de barras de un resumendf.groupby("city")["salary"].mean().plot.bar()
Barras horizontales ordenadasdf["city"].value_counts().sort_values().plot.barh()
Histogramadf["salary"].plot.hist(bins=20)
Gráfico de dispersióndf.plot.scatter(x="age", y="salary")
Diagrama de caja por grupodf.boxplot(column="salary", by="city")
Título y etiqueta de ejeax = df.plot(x="date", y="salary", title="Salary") ax.set_ylabel("EUR")
Mostrar o guardar el gráficoplt.show(), ax.figure.savefig("salary.png", dpi=150)

pandas 3: formas antiguas y qué escribir ahora

El código copiado de tutoriales antiguos suele fallar o lanzar avisos en pandas 3. Usa en su lugar las formas de la columna pandas 3.

Tareapandas 3Forma antigua
Función en cada celdadf.map(f)df.applymap(f)
Rellenar con la fila anteriordf.ffill()df.fillna(method="ffill")
Añadir filaspd.concat([df, new_rows])df.append(new_rows)
Remuestreo a fin de mests["salary"].resample("ME").sum()resample("M")
Fechas por horapd.date_range("2026-01-01", periods=24, freq="h")freq="H"
Asignar un valordf.loc[0, "age"] = 37df["age"][0] = 37
Cambiar un subconjunto filtradohigh = df[df["salary"] > 5000] high["salary"] = 0high = df[df["salary"] > 5000].copy()
¿Es una columna de texto?df["name"].dtype == "str"df["name"].dtype == object

El código de pandas que un analista de datos usa a diario, ordenado por tarea: crear y cargar datos, inspeccionarlos, seleccionar y filtrar filas, añadir columnas, limpiar valores faltantes, trabajar con texto y fechas, agrupar y agregar, reorganizar, combinar y graficar. Cada fila es un fragmento corto que puedes pegar, con una línea que explica qué hace.

Todo está escrito para pandas 3, la versión que usa Coddy: las columnas de texto usan el nuevo dtype str, Copy-on-Write está siempre activo y las APIs eliminadas, como applymap y fillna(method=...), solo aparecen en la tabla de formas antiguas. Los ejemplos usan un DataFrame df con las columnas name, city, team, age, salary, date y email. ¿Empiezas con Python? Arranca por la hoja de trucos de Python y el playground de Python, y ten a mano las hojas de trucos de NumPy, Matplotlib y scikit-learn junto a esta.

Preguntas frecuentes sobre la hoja de trucos de pandas

¿Esta hoja de trucos de pandas es gratis?
Sí. Esta hoja de trucos de pandas es totalmente gratis y no necesitas registrarte. Guárdala en marcadores o imprímela en PDF desde tu navegador, y vuelve cuando necesites la llamada exacta para un groupby, un merge o una tabla dinámica.
¿Qué versión de pandas cubre esta hoja de trucos?
pandas 3. Las columnas de texto usan el nuevo dtype str, Copy-on-Write está siempre activo y las llamadas eliminadas en pandas 3 (applymap, fillna(method=...), append, los alias de frecuencia M y H) solo aparecen en la última tabla, junto a lo que debes escribir en su lugar. Casi todos los fragmentos también funcionan en pandas 2.2, salvo las filas que dependen del dtype str o de Copy-on-Write.
¿Cuál es la diferencia entre loc e iloc?
loc selecciona por etiqueta: los valores del índice y los nombres de columna, y un slice como df.loc[0:2] incluye su final. iloc selecciona por posición entera, como una lista de Python, así que df.iloc[0:2] devuelve las dos primeras filas y excluye el final. Usa loc con una condición para filtrar filas y elegir columnas en un solo paso: df.loc[df["age"] > 30, ["name"]].
¿Cómo filtro un DataFrame con varias condiciones?
Pon cada condición entre paréntesis y únelas con & para y, | para o, y ~ para no: df[(df["age"] > 30) & (df["city"] == "Oslo")]. Los operadores and y or de Python no funcionan con columnas completas. Para filtros largos, df.query("age > 30 and city == 'Oslo'") se lee mejor.
¿Cuál es la diferencia entre merge, join y concat?
merge combina dos DataFrames por columnas clave, como un join de SQL, con how="inner", "left", "right" u "outer". join es un atajo que hace el merge por el índice. concat no empareja claves: apila los DataFrames uno encima de otro, o lado a lado con axis=1.
¿Por qué mi asignación no cambia el DataFrame?
Desde pandas 3, Copy-on-Write hace que cada selección se comporte como una copia. Una asignación encadenada como df["age"][0] = 37 modifica un objeto temporal y deja df sin cambios. Escríbela como una sola llamada a loc: df.loc[0, "age"] = 37. Métodos como dropna y fillna también devuelven un objeto nuevo, así que asigna el resultado.
¿Puedo ejecutar código de pandas online?
Sí. El playground de Matplotlib, gratuito, ejecuta Python con pandas, NumPy, Matplotlib y scikit-learn en tu navegador, así que puedes pegar cualquier fragmento de esta hoja de trucos y ejecutarlo sin instalar nada. El curso de Machine Learning de Coddy enseña pandas paso a paso, desde tu primer DataFrame hasta los datos que alimentan un modelo.
Ilustración de los lenguajes de programación de Coddy

Aprende Pandas con Coddy

COMENZAR