Pandas: Manipulación de datos

Aprende técnicas de manipulación de datos en Pandas. Descubre cómo transformar y organizar tus datos eficientemente con esta poderosa biblioteca de Python.

Aprende Pandas GRATIS y certifícate

La manipulación de datos constituye una fase esencial en cualquier proyecto de análisis. Los científicos de datos dedican entre el 50% y el 80% de su tiempo a preparar, transformar y reorganizar datos antes de poder extraer conocimiento valioso.

Pandas proporciona un ecosistema completo de herramientas que permiten realizar estas operaciones de manera eficiente, convirtiendo datos brutos en información procesable mediante operaciones intuitivas y de alto rendimiento.

En este módulo profundizaremos en las técnicas fundamentales que te permitirán:

  • Seleccionar subconjuntos específicos de tus datos
  • Transformar valores según necesidades analíticas
  • Agregar y resumir información
  • Combinar múltiples fuentes de datos

Estas habilidades esenciales forman la columna vertebral de cualquier proyecto de análisis, independientemente del sector o nivel de complejidad.

import pandas as pd
import numpy as np

# Creamos un DataFrame de ejemplo
datos = {
    'producto': ['Laptop', 'Smartphone', 'Tablet', 'Auriculares', 'Monitor'],
    'precio': [1200, 800, 500, 100, 300],
    'stock': [15, 25, 10, 30, 5],
    'categoría': ['Informática', 'Móviles', 'Informática', 'Audio', 'Informática'],
    'fecha_actualización': ['2023-01-15', '2023-01-20', '2023-01-10', '2023-01-25', '2023-01-05']
}

df = pd.DataFrame(datos)
df['fecha_actualización'] = pd.to_datetime(df['fecha_actualización'])

print(df)

2. Selección y filtrado de datos

La capacidad para extraer subconjuntos precisos de información es fundamental en el análisis de datos. Pandas ofrece múltiples métodos para seleccionar exactamente lo que necesitas.

2.1. Métodos básicos de selección

Para seleccionar columnas específicas puedes utilizar varias notaciones:

# Seleccionar una columna (devuelve una Series)
precios = df['precio']

# Seleccionar múltiples columnas (devuelve un DataFrame)
productos_precios = df[['producto', 'precio']]

La selección de filas por posición se realiza mediante slicing o métodos específicos:

# Seleccionar la primera fila
primera_fila = df.iloc[0]

# Seleccionar las tres primeras filas
primeras_filas = df[:3]

# Seleccionar filas del índice 1 al 3 (sin incluir el 4)
filas_intermedias = df.iloc[1:4]

2.2. Filtrado condicional

El filtrado por condiciones permite extraer datos que cumplen criterios específicos:

# Productos con precio mayor a 500
productos_caros = df[df['precio'] > 500]

# Productos de la categoría 'Informática'
informatica = df[df['categoría'] == 'Informática']

# Productos caros de informática (combinando condiciones)
informatica_caros = df[(df['categoría'] == 'Informática') & (df['precio'] > 300)]

# Productos con stock bajo o precio alto
atencion_especial = df[(df['stock'] < 10) | (df['precio'] > 1000)]

2.3. Loc e iloc para selección precisa

Los métodos loc e iloc ofrecen control avanzado sobre la selección:

# iloc: selección basada en posición (índices numéricos)
elemento = df.iloc[2, 3]  # Valor en la fila 2, columna 3
fila_columnas = df.iloc[0, [0, 2, 4]]  # Primera fila; columnas 0, 2 y 4

# loc: selección basada en etiquetas
df_subset = df.loc[1:3, ['producto', 'precio']]

# Selección condicional con loc
productos_seleccionados = df.loc[df['stock'] > 20, ['producto', 'precio', 'stock']]

2.4. Método query para filtrado expresivo

El método query proporciona una sintaxis más legible para filtros complejos:

# Equivalente a df[(df['precio'] > 300) & (df['stock'] >= 10)]
resultado = df.query('precio > 300 and stock >= 10')

# Uso de variables en query
precio_minimo = 300
categoria_buscada = 'Informática'
resultado = df.query('precio > @precio_minimo and categoría == @categoria_buscada')

2.5. Selección basada en fechas

Para datos temporales, Pandas ofrece métodos específicos de filtrado:

# Productos actualizados después de una fecha
recientes = df[df['fecha_actualización'] > '2023-01-15']

# Utilizar métodos de datetime para filtrado más granular
enero_medio = df[df['fecha_actualización'].dt.day > 15]

3. Transformación de datos

La transformación de datos nos permite modificar y adaptar la información para satisfacer nuestras necesidades analíticas específicas.

3.1. Aplicación de funciones con apply, map y applymap

Estas funciones permiten realizar transformaciones personalizadas:

# apply en Series: aplicar función a cada elemento
df['precio_con_iva'] = df['precio'].apply(lambda x: x * 1.21)

# apply en DataFrame: aplicar función a filas o columnas
df['resumen'] = df.apply(lambda row: f"{row['producto']} - {row['precio']}€", axis=1)

# map: transformar valores en una Series mediante un diccionario o función
categorias_simplificadas = {'Informática': 'Tech', 'Móviles': 'Tech', 'Audio': 'Audio'}
df['categoria_simple'] = df['categoría'].map(categorias_simplificadas)

# applymap: aplicar función a cada elemento del DataFrame
df_formateado = df[['precio', 'stock']].applymap(lambda x: f"{x:,}")

3.2. Modificación de valores con replace y where

Para sustituir valores específicos o aplicar cambios condicionales:

# Reemplazar valores
df['categoría'] = df['categoría'].replace('Móviles', 'Smartphones')

# Reemplazar múltiples valores
df['categoría'] = df['categoría'].replace({'Audio': 'Sonido', 'Informática': 'Computación'})

# where: reemplazar valores según condición
df['precio_rebajado'] = df['precio'].where(df['stock'] > 20, df['precio'] * 0.9)

3.3. Conversión de tipos de datos

La conversión de tipos es crucial para asegurar operaciones correctas:

# Convertir a numérico
df['precio'] = pd.to_numeric(df['precio'], errors='coerce')

# Convertir a categórica (útil para optimizar memoria)
df['categoría'] = df['categoría'].astype('category')

# Convertir a datetime
df['fecha_actualización'] = pd.to_datetime(df['fecha_actualización'])

# Conversiones múltiples con astype
conversiones = {'precio': 'float32', 'stock': 'int32'}
df = df.astype(conversiones)

3.4. Creación de columnas basadas en cálculos

Añadir nuevos campos calculados es una operación habitual:

# Columna simple basada en cálculo
df['valor_inventario'] = df['precio'] * df['stock']

# Columna basada en múltiples condiciones
df['nivel_stock'] = np.where(df['stock'] > 20, 'Alto', 
                            np.where(df['stock'] > 10, 'Medio', 'Bajo'))

# Cálculos utilizando métodos encadenados
df['precio_relativo'] = df['precio'] / df['precio'].mean()
df['precio_normalizado'] = (df['precio'] - df['precio'].min()) / (df['precio'].max() - df['precio'].min())

4. Operaciones con filas y columnas

El manejo eficiente de la estructura de tus datos es fundamental para adaptarlos a tus necesidades analíticas.

4.1. Añadir filas y columnas

Para expandir tus datos con nueva información:

# Añadir una nueva columna
df['descuento'] = 0.05

# Añadir columna basada en lógica condicional
df['precio_final'] = df['precio'] * (1 - df['descuento'])

# Añadir fila utilizando loc
nuevo_indice = len(df)
df.loc[nuevo_indice] = ['Webcam', 50, 20, 'Informática', '2023-01-30', 0.05, 47.5]

# Añadir fila mediante concat
nuevo_producto = pd.DataFrame([['Teclado', 45, 15, 'Informática', '2023-01-28', 0.05, 42.75]], 
                            columns=df.columns)
df = pd.concat([df, nuevo_producto], ignore_index=True)

4.2. Eliminar filas y columnas

Para simplificar tu DataFrame eliminando elementos innecesarios:

# Eliminar columnas
df_reducido = df.drop(columns=['descuento'])

# Eliminar múltiples columnas
df_esencial = df.drop(columns=['descuento', 'fecha_actualización'])

# Eliminar filas por índice
df_sin_primero = df.drop(index=0)

# Eliminar filas por condición
df_filtrado = df.drop(index=df[df['stock'] < 10].index)

4.3. Renombrar columnas

Para mejorar la claridad y consistencia de tus datos:

# Renombrar una columna
df = df.rename(columns={'precio': 'precio_base'})

# Renombrar múltiples columnas
df = df.rename(columns={'precio_base': 'precio', 'categoría': 'categoria'})

# Convertir nombres a minúsculas
df.columns = df.columns.str.lower()

# Reemplazar espacios por guiones bajos
df.columns = df.columns.str.replace(' ', '_')

4.4. Reordenar filas y columnas

La reorganización de datos mejora la legibilidad y facilita el análisis:

# Reordenar columnas
columnas_ordenadas = ['producto', 'categoria', 'precio', 'stock', 'fecha_actualizacion']
df = df[columnas_ordenadas]

# Ordenar filas por un valor
df_ordenado_precio = df.sort_values('precio', ascending=False)

# Ordenar por múltiples columnas
df_ordenado = df.sort_values(['categoria', 'precio'])

# Ordenar índice
df_indice_ordenado = df.sort_index()

5. Indexación avanzada

El sistema de indexación de Pandas es una de sus características más distintivas, permitiendo un acceso eficiente a los datos y facilitando operaciones complejas.

5.1. Manipulación de índices

Los índices funcionan como la estructura organizativa de tus datos:

# Establecer una columna como índice
df_indexed = df.set_index('producto')

# Acceder a una fila por índice
laptop_info = df_indexed.loc['Laptop']

# Restablecer el índice (convertir índice a columna)
df_reset = df_indexed.reset_index()

# Acceso por rango de índices
subset = df_indexed.loc['Laptop':'Tablet']

5.2. Índices jerárquicos (MultiIndex)

Los índices multinivel permiten representar datos con mayor complejidad dimensional:

# Crear MultiIndex
df_multi = df.set_index(['categoria', 'producto'])

# Acceder a un nivel específico del índice
informatica = df_multi.loc['Informática']

# Acceder a una combinación específica de niveles
laptop_info = df_multi.loc[('Informática', 'Laptop')]

# Seleccionar usando slice en el primer nivel y valor específico en el segundo
subset = df_multi.loc[('Inform
Empezar curso de Pandas

Lecciones de este módulo de Pandas

Lecciones de programación del módulo Manipulación de datos del curso de Pandas.

Ejercicios de programación en este módulo de Pandas

Evalúa tus conocimientos en Manipulación de datos con ejercicios de programación Manipulación de datos de tipo Test, Puzzle, Código y Proyecto con VSCode.