Tutorial de Pandas
Aprende pandas desde cero: Series, DataFrames, filtrado, groupby, valores faltantes, combinación y visualización de datos con ejemplos en Python.
pandas es la biblioteca Python más utilizada para trabajar con datos estructurados (tabulares). Proporciona dos estructuras de datos fundamentales — Series y DataFrame — junto con un amplio conjunto de herramientas para cargar, limpiar, transformar, agregar y visualizar datos.
Este capítulo cubre todo lo que necesitas para pasar de cero a productivo con pandas: instalación, estructuras de datos, lectura de archivos, selección y filtrado de datos, manejo de valores faltantes, agrupación, combinación y graficación básica.
Instalación de pandas
Instala pandas con pip:
pip install pandasSi planeas seguir los ejemplos de graficación más adelante en este capítulo, instala también Matplotlib:
pip install matplotlibDespués de la instalación, importa pandas usando el alias convencional pd:
import pandas as pdLas dos estructuras de datos principales
Series
Una Series es un array unidimensional con etiquetas. Cada elemento tiene un valor y una etiqueta de índice correspondiente (por defecto, enteros empezando desde 0).
import pandas as pd
scores = pd.Series([88.5, 92.0, 79.5, 95.0])
print(scores)Salida:
0 88.5
1 92.0
2 79.5
3 95.0
dtype: float64Puedes proporcionar etiquetas de índice personalizadas para que los datos sean autodescriptivos:
scores = pd.Series(
[88.5, 92.0, 79.5, 95.0],
index=['Alice', 'Bob', 'Carol', 'Dave']
)
print(scores)
print(scores['Bob']) # 92.0Salida:
Alice 88.5
Bob 92.0
Carol 79.5
Dave 95.0
dtype: float64
92.0Una Series con un índice significativo es similar a un diccionario de Python, pero admite operaciones vectorizadas y está integrada con el resto de la API de pandas.
DataFrame
Un DataFrame es una tabla bidimensional con filas y columnas etiquetadas — imagínalo como una hoja de cálculo o una tabla SQL cargada en Python. Cada columna es internamente una Series que comparte el mismo índice de fila.
Creación de un DataFrame a partir de un diccionario de listas
Salida:
name age score
0 Alice 25 88.5
1 Bob 30 92.0
2 Carol 28 79.5
3 Dave 35 95.0Las claves del diccionario se convierten en nombres de columnas; los valores del diccionario se convierten en columnas. El índice de fila toma por defecto los valores 0, 1, 2, 3.
Atributos útiles para inspeccionar un DataFrame justo después de crearlo:
| Atributo / Método | Qué devuelve |
|---|---|
df.shape | Tupla de (filas, columnas) |
df.dtypes | Tipo de dato de cada columna |
df.columns | Etiquetas de columnas |
df.index | Etiquetas de filas |
df.head(n) | Primeras n filas (por defecto 5) |
df.tail(n) | Últimas n filas (por defecto 5) |
df.describe() | Estadísticas resumen para columnas numéricas |
df.info() | Nombres de columnas, tipos y conteos no nulos |
Lectura de datos desde archivos
En proyectos reales raramente se crean DataFrames a mano. pandas puede leer docenas de formatos de archivo.
Lectura de un archivo 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() infiere automáticamente los tipos de columna. Opciones comunes:
sep=';'— cambiar el delimitador (por defecto es la coma)index_col='id'— usar una columna como índice de filaparse_dates=['date']— parsear una columna como fecha y horanrows=500— leer sólo las primeras 500 filas (útil para archivos grandes)
Lectura de un archivo Excel
df = pd.read_excel('report.xlsx', sheet_name='Sheet1')Requiere la dependencia opcional openpyxl: pip install openpyxl.
Escritura de datos de vuelta a un archivo
df.to_csv('output.csv', index=False) # CSV without the row index column
df.to_excel('output.xlsx', index=False) # ExcelSelección de datos
Selección de columnas
Selecciona una sola columna para obtener una Series:
ages = df['age']
print(type(ages)) # <class 'pandas.core.series.Series'>Selecciona múltiples columnas para obtener un DataFrame:
subset = df[['name', 'score']]
print(subset)Salida:
name score
0 Alice 88.5
1 Bob 92.0
2 Carol 79.5
3 Dave 95.0Selección de filas con loc e iloc
pandas proporciona dos selectores de filas principales:
loc— selecciona por etiqueta (valor del índice)iloc— selecciona por posición entera (base 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)Salida:
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.0Nótese la diferencia: loc[1:2] es basado en etiquetas e inclusivo en ambos extremos; iloc[0:2] es basado en posición y exclusivo en el extremo derecho (como los slices normales de Python).
También puedes seleccionar una celda específica:
print(df.loc[1, 'score']) # 92.0 — by label
print(df.iloc[0, 2]) # 88.5 — by positionFiltrado de filas
Filtra filas usando una condición booleana dentro de corchetes:
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])Salida:
name age score
1 Bob 30 92.0
3 Dave 35 95.0Combina múltiples condiciones con & (y) o | (o). Siempre encierra cada condición entre paréntesis:
# Age > 25 AND score >= 90
print(df[(df['age'] > 25) & (df['score'] >= 90)])Salida:
name age score
1 Bob 30 92.0
3 Dave 35 95.0Usa isin() para filtrar por una lista de valores:
print(df[df['name'].isin(['Alice', 'Carol'])])Adición y modificación de columnas
Añade una nueva columna asignándole un valor:
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)Salida:
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() ejecuta una función sobre cada elemento de una columna. Para aritmética simple puedes usar operaciones vectorizadas directamente — son más rápidas que apply():
df['score_scaled'] = df['score'] / 100 # no apply() neededRenombra columnas con rename():
df = df.rename(columns={'score': 'exam_score', 'age': 'years_old'})Elimina una columna con drop():
df = df.drop(columns=['grade'])Ordenamiento de datos
Ordena un DataFrame por una o más columnas 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))Salida:
department name salary
1 Eng Bob 95000
0 Eng Alice 90000
4 Eng Eve 88000
3 HR Dave 72000
2 HR Carol 70000Ordena por múltiples columnas — por ejemplo, departamento de forma ascendente y luego salario de forma descendente dentro de cada departamento:
df_sorted = df.sort_values(['department', 'salary'], ascending=[True, False])
print(df_sorted)Manejo de valores faltantes
Los conjuntos de datos del mundo real casi siempre contienen valores faltantes. pandas los 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())Salida:
name 0
age 1
score 1
dtype: int64Relleno de valores faltantes
Reemplaza NaN con un valor fijo o un estadístico:
df_filled = df.fillna({
'age': df['age'].mean(), # fill with column mean
'score': df['score'].median() # fill with column median
})
print(df_filled)Salida:
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.0Eliminación de filas con valores faltantes
df_dropped = df.dropna()
print(df_dropped)Salida:
name age score
0 Alice 25.0 88.5
3 Dave 35.0 95.0Cuándo rellenar vs. cuándo eliminar: eliminar filas hace perder datos y puede introducir sesgo si los valores no faltan de forma aleatoria. Rellenar (imputación) es generalmente preferible cuando los datos faltantes son escasos. Para flujos de trabajo de aprendizaje automático, consulta el capítulo Scale para estandarizar características numéricas después de la imputación.
Agrupación de datos
groupby() divide el DataFrame en grupos, aplica una función a cada grupo y combina los resultados. Es el equivalente pandas de GROUP BY en 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())Salida:
department
Eng 91000.0
HR 71000.0
Name: salary, dtype: float64Aplica múltiples funciones de agregación a la vez usando agg():
print(df.groupby('department')['salary'].agg(['mean', 'min', 'max', 'count']))Salida:
mean min max count
department
Eng 91000.0 88000 95000 3
HR 71000.0 70000 72000 2Combinación y concatenación de DataFrames
Combinación (como JOIN en SQL)
Usa pd.merge() para combinar dos DataFrames en una columna clave compartida:
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)Salida:
emp_id name dept_id dept_name
0 1 Alice 10 Engineering
1 2 Bob 20 HR
2 3 Carol 10 EngineeringEl valor por defecto es una combinación interna (inner join, solo filas con una clave coincidente en ambos DataFrames). Controla el tipo de combinación con how:
how='left'— todas las filas del DataFrame izquierdo, filas coincidentes del derechohow='right'— todas las filas del DataFrame derecho, filas coincidentes del izquierdohow='outer'— todas las filas de ambos DataFrames;NaNdonde no hay coincidencia
Concatenación (apilamiento de DataFrames)
Usa pd.concat() para apilar DataFrames con las mismas columnas 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)Salida:
name sales
0 Alice 120
1 Bob 95
2 Carol 110
3 Dave 130ignore_index=True restablece el índice de fila para que vaya de 0 a 3 en lugar de repetir 0 y 1 de cada DataFrame fuente.
Estadísticas descriptivas
pandas facilita el cálculo de estadísticas resumen sobre un DataFrame completo o columnas individuales:
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())Salida:
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.000000Las estadísticas individuales también están disponibles como métodos directos: df['score'].mean(), df['score'].std(), df['score'].median(), df['age'].max().
Visualización básica de datos
pandas se integra con Matplotlib para que puedas graficar directamente desde un DataFrame con el método .plot(). Instala Matplotlib primero si aún no lo has hecho: pip install matplotlib.
Gráfico de líneas
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 comunes para el parámetro kind:
kind | Tipo de gráfico |
|---|---|
'line' | Gráfico de líneas |
'bar' | Gráfico de barras vertical |
'barh' | Gráfico de barras horizontal |
'hist' | Histograma |
'box' | Diagrama de caja |
'scatter' | Diagrama de dispersión (requiere x e y) |
'pie' | Gráfico de tarta |
Para graficación más avanzada, consulta los capítulos Matplotlib Introduction y Matplotlib Scatter Plot.
Errores comunes
SettingWithCopyWarning: cuando filtras un DataFrame y luego intentas modificar el resultado, pandas puede advertirte que estás modificando una copia en lugar del original. Usa .copy() para ser explícito:
# Safe: work on an explicit copy
young = df[df['age'] < 30].copy()
young['group'] = 'junior'Indexación encadenada: df['col'][0] = value puede o no modificar el DataFrame original. Usa siempre df.loc[0, 'col'] = value para la asignación.
Nombres de columnas con espacios: si una columna se llama "first name", debes usar la notación de corchetes — df['first name'] — no la notación de punto (df.first name es un error de sintaxis).
Entero vs. flotante después de fillna: rellenar NaN en una columna de enteros con un número promueve la columna a float64 porque NaN es un flotante. Usa pd.Int64Dtype() (entero nullable) si necesitas mantener la semántica entera con valores faltantes.
Capítulos relacionados
- NumPy Tutorial — la biblioteca de arrays sobre la que está construido pandas
- Matplotlib Introduction — crea gráficos de calidad de publicación a partir de tus datos
- Matplotlib Scatter Plot — visualiza relaciones entre dos variables numéricas
- Data Distribution — comprende cómo se distribuyen los valores en un conjunto de datos
- Scale — normaliza y estandariza características numéricas antes del modelado
- Categorical Data — codifica columnas no numéricas para el aprendizaje automático
- Train/Test Split — divide un DataFrame de pandas en conjuntos de entrenamiento y prueba
- SciPy Tutorial — funciones estadísticas y científicas que complementan pandas