W3docs

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 pandas

Si planeas seguir los ejemplos de graficación más adelante en este capítulo, instala también Matplotlib:

pip install matplotlib

Después de la instalación, importa pandas usando el alias convencional pd:

import pandas as pd

Las 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: float64

Puedes 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.0

Salida:

Alice    88.5
Bob      92.0
Carol    79.5
Dave     95.0
dtype: float64
92.0

Una 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

python— editable, runs on the server

Salida:

    name  age  score
0  Alice   25   88.5
1    Bob   30   92.0
2  Carol   28   79.5
3   Dave   35   95.0

Las 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étodoQué devuelve
df.shapeTupla de (filas, columnas)
df.dtypesTipo de dato de cada columna
df.columnsEtiquetas de columnas
df.indexEtiquetas 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 fila
  • parse_dates=['date'] — parsear una columna como fecha y hora
  • nrows=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)  # Excel

Selecció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.0

Selecció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.0

Nó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 position

Filtrado 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.0

Combina 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.0

Usa 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     A

apply() 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() needed

Renombra 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   70000

Ordena 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: int64

Relleno 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.0

Eliminació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.0

Cuá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: float64

Aplica 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      2

Combinació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  Engineering

El 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 derecho
  • how='right' — todas las filas del DataFrame derecho, filas coincidentes del izquierdo
  • how='outer' — todas las filas de ambos DataFrames; NaN donde 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    130

ignore_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.000000

Las 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:

kindTipo 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
Was this page helpful?