Lección 6 de 29Módulo 2: Pandas - Manipulación de Datos

06. Introducción a Pandas

Series, DataFrames y las estructuras fundamentales de Pandas

20 minutos

Bienvenido al Módulo 2. Pandas es la librería más importante para análisis de datos en Python. En esta lección dominarás sus estructuras fundamentales: Series y DataFrames.

¿Qué es Pandas?

Pandas es una librería de Python para manipulación y análisis de datos estructurados. Es como Excel con superpoderes:

  • 📊 Maneja datasets de millones de filas (Excel limita a ~1M)
  • ⚡ Operaciones ultra rápidas en datos
  • 🔄 Lee/escribe múltiples formatos (CSV, Excel, JSON, SQL, etc.)
  • 📈 Integración perfecta con visualización y machine learning

💡 Dato: El 95% de los analistas de datos profesionales usan Pandas diariamente. Es LA herramienta esencial para data analytics.

Instalación y primera importación

# Verificar instalación (ya debería estar con Anaconda)
import pandas as pd
import numpy as np

print(f"Pandas version: {pd.__version__}")
print(f"NumPy version: {np.__version__}")

Convención de importación

# Siempre importa Pandas con el alias 'pd'
import pandas as pd  # ✅ Estándar universal

# No hagas esto:
import pandas        # ❌ Sin alias
import pandas as pnd # ❌ Alias no estándar

Series: Arrays unidimensionales

Una Serie es como una columna de Excel o una lista mejorada con etiquetas.

Crear Series

import pandas as pd

# Desde lista
ventas = pd.Series([1200, 1450, 1100, 1800, 1950])
print(ventas)

Resultado:

0    1200
1    1450
2    1100
3    1800
4    1950
dtype: int64

Series con índice personalizado

# Índice personalizado
ventas_diarias = pd.Series(
    [1200, 1450, 1100, 1800, 1950, 2100, 1750],
    index=['Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb', 'Dom']
)
print(ventas_diarias)

# Acceder por índice
print(ventas_diarias['Lun'])    # 1200
print(ventas_diarias['Sáb'])    # 2100

# Acceder por posición (como lista)
print(ventas_diarias[0])        # 1200
print(ventas_diarias[-1])       # 1750

# Slice
print(ventas_diarias['Lun':'Mié'])  # Lun, Mar, Mié

Series desde diccionario

# Crear desde diccionario (la forma más común)
metricas = pd.Series({
    'usuarios': 15000,
    'conversiones': 750,
    'ingresos': 45000,
    'ctr': 3.5
})
print(metricas)

Resultado:

usuarios         15000.0
conversiones       750.0
ingresos         45000.0
ctr                  3.5
dtype: float64

Operaciones con Series

ventas = pd.Series([1200, 1450, 1100, 1800, 1950])

# Operaciones matemáticas
print(ventas + 100)        # Suma 100 a cada elemento
print(ventas * 1.10)       # Aplica 10% de aumento
print(ventas / 1000)       # Convierte a miles

# Estadísticas descriptivas
print(f"Suma: {ventas.sum()}")            # 8500
print(f"Promedio: {ventas.mean():.2f}")   # 1700.00
print(f"Mediana: {ventas.median()}")      # 1450.0
print(f"Máximo: {ventas.max()}")          # 1950
print(f"Mínimo: {ventas.min()}")          # 1100
print(f"Desv. estándar: {ventas.std():.2f}") # 344.82

# Método describe() (resumen completo)
print(ventas.describe())

Resultado de describe():

count     5.000000
mean   1700.000000
std     356.789190
min    1100.000000
25%    1200.000000
50%    1450.000000
75%    1800.000000
max    1950.000000
dtype: float64

DataFrames: Tablas completas

Un DataFrame es una tabla bidimensional (filas y columnas). Es la estructura principal de Pandas.

Crear DataFrames

# Desde diccionario (cada key es una columna)
ventas_df = pd.DataFrame({
    'producto': ['Laptop', 'Mouse', 'Teclado', 'Monitor'],
    'cantidad': [2, 10, 5, 3],
    'precio': [800, 25, 60, 300]
})

print(ventas_df)

Resultado:

   producto  cantidad  precio
0    Laptop         2     800
1     Mouse        10      25
2  Teclado         5      60
3   Monitor         3     300

Desde lista de diccionarios

# Cada diccionario es una fila
transacciones = pd.DataFrame([
    {'fecha': '2024-01-15', 'producto': 'Laptop', 'cantidad': 2, 'precio': 800},
    {'fecha': '2024-01-16', 'producto': 'Mouse', 'cantidad': 10, 'precio': 25},
    {'fecha': '2024-01-16', 'producto': 'Teclado', 'cantidad': 5, 'precio': 60},
    {'fecha': '2024-01-17', 'producto': 'Monitor', 'cantidad': 3, 'precio': 300}
])

print(transacciones)

Propiedades básicas del DataFrame

# Ver primeras filas
print(transacciones.head())      # Primeras 5 filas (default)
print(transacciones.head(2))     # Primeras 2 filas

# Ver últimas filas
print(transacciones.tail())      # Últimas 5 filas
print(transacciones.tail(2))     # Últimas 2 filas

# Información del DataFrame
print(transacciones.info())

# Dimensiones
print(f"Filas: {transacciones.shape[0]}")
print(f"Columnas: {transacciones.shape[1]}")
print(f"Shape: {transacciones.shape}")     # (4, 4)

# Nombres de columnas
print(transacciones.columns)
# Index(['fecha', 'producto', 'cantidad', 'precio'], dtype='object')

# Tipos de datos
print(transacciones.dtypes)

Acceder a columnas

# Forma 1: Como atributo (solo si nombre sin espacios)
productos = transacciones.producto
print(productos)

# Forma 2: Como diccionario (recomendado)
productos = transacciones['producto']
print(productos)

# Múltiples columnas
subset = transacciones[['producto', 'precio']]
print(subset)

Acceder a filas

# Por posición con iloc
primera_fila = transacciones.iloc[0]
print(primera_fila)

# Rango de filas
primeras_dos = transacciones.iloc[0:2]
print(primeras_dos)

# Por índice con loc (más adelante veremos índices personalizados)
# Por ahora, iloc es suficiente

Operaciones con columnas

Crear nuevas columnas

# Calcular total por transacción
transacciones['total'] = transacciones['cantidad'] * transacciones['precio']
print(transacciones)

Resultado:

        fecha producto  cantidad  precio  total
0  2024-01-15   Laptop         2     800   1600
1  2024-01-16    Mouse        10      25    250
2  2024-01-16  Teclado         5      60    300
3  2024-01-17  Monitor         3     300    900

Operaciones matemáticas en columnas

# Aplicar descuento del 10%
transacciones['precio_descuento'] = transacciones['precio'] * 0.9

# Calcular IVA (21%)
transacciones['iva'] = transacciones['total'] * 0.21

# Total con IVA
transacciones['total_con_iva'] = transacciones['total'] + transacciones['iva']

print(transacciones[['producto', 'total', 'iva', 'total_con_iva']])

Eliminar columnas

# Eliminar columna (no modifica el original)
df_sin_iva = transacciones.drop('iva', axis=1)

# Eliminar columna (modifica el original)
transacciones.drop('precio_descuento', axis=1, inplace=True)

# Eliminar múltiples columnas
# transacciones.drop(['col1', 'col2'], axis=1, inplace=True)

Proyecto práctico: Análisis de campaña digital

import pandas as pd

# Dataset de campaña de marketing
campañas = pd.DataFrame({
    'campaña': [
        'Black Friday Email',
        'Google Ads - Search',
        'Facebook Ads',
        'Instagram Stories',
        'LinkedIn Sponsored'
    ],
    'impresiones': [50000, 120000, 200000, 180000, 45000],
    'clics': [2500, 4800, 6000, 7200, 1350],
    'conversiones': [125, 192, 240, 288, 54],
    'costo': [500, 2400, 3000, 2700, 900]
})

print("="*60)
print("ANÁLISIS DE CAMPAÑAS DIGITALES")
print("="*60)
print(campañas)
print()

# Calcular métricas
campañas['ctr'] = (campañas['clics'] / campañas['impresiones']) * 100
campañas['conversion_rate'] = (campañas['conversiones'] / campañas['clics']) * 100
campañas['cpc'] = campañas['costo'] / campañas['clics']
campañas['cpa'] = campañas['costo'] / campañas['conversiones']

# Asumiendo valor de conversión de $100
valor_conversion = 100
campañas['ingresos'] = campañas['conversiones'] * valor_conversion
campañas['roi'] = ((campañas['ingresos'] - campañas['costo']) / campañas['costo']) * 100

# Mostrar métricas principales
print("MÉTRICAS CALCULADAS:")
print(campañas[['campaña', 'ctr', 'conversion_rate', 'roi']].round(2))
print()

# Estadísticas generales
print("RESUMEN GENERAL:")
print(f"Total invertido: ${campañas['costo'].sum():,}")
print(f"Total conversiones: {campañas['conversiones'].sum()}")
print(f"Ingresos generados: ${campañas['ingresos'].sum():,}")
print(f"CTR promedio: {campañas['ctr'].mean():.2f}%")
print(f"Conversion rate promedio: {campañas['conversion_rate'].mean():.2f}%")
print(f"ROI promedio: {campañas['roi'].mean():.1f}%")
print()

# Mejor campaña por ROI
mejor_roi_idx = campañas['roi'].idxmax()
mejor_campaña = campañas.loc[mejor_roi_idx]
print("🏆 MEJOR CAMPAÑA (ROI):")
print(f"  {mejor_campaña['campaña']}")
print(f"  ROI: {mejor_campaña['roi']:.1f}%")
print(f"  Conversiones: {mejor_campaña['conversiones']}")
print(f"  CPA: ${mejor_campaña['cpa']:.2f}")

Resultado:

============================================================
ANÁLISIS DE CAMPAÑAS DIGITALES
============================================================
                 campaña  impresiones  clics  conversiones  costo
0   Black Friday Email         50000   2500           125    500
1  Google Ads - Search        120000   4800           192   2400
2         Facebook Ads        200000   6000           240   3000
3     Instagram Stories        180000   7200           288   2700
4   LinkedIn Sponsored         45000   1350            54    900

MÉTRICAS CALCULADAS:
                 campaña   ctr  conversion_rate    roi
0   Black Friday Email  5.00             5.00  2400.0
1  Google Ads - Search  4.00             4.00   700.0
2         Facebook Ads  3.00             4.00   700.0
3     Instagram Stories  4.00             4.00   966.7
4   LinkedIn Sponsored  3.00             4.00   500.0

RESUMEN GENERAL:
Total invertido: $9,500
Total conversiones: 899
Ingresos generados: $89,900
CTR promedio: 3.80%
Conversion rate promedio: 4.20%
ROI promedio: 1053.3%

🏆 MEJOR CAMPAÑA (ROI):
  Black Friday Email
  ROI: 2400.0%
  Conversiones: 125
  CPA: $4.00

Métodos esenciales de DataFrames

Información y estadísticas

# Resumen estadístico de columnas numéricas
print(campañas.describe())

# Información del DataFrame
print(campañas.info())

# Contar valores únicos
print(campañas['campaña'].nunique())  # Número de campañas únicas

# Ver valores únicos
print(campañas['campaña'].unique())

# Contar frecuencia de cada valor
print(campañas['conversiones'].value_counts())

Ordenar datos

# Ordenar por ROI descendente
campañas_ordenadas = campañas.sort_values('roi', ascending=False)
print(campañas_ordenadas[['campaña', 'roi']].head())

# Ordenar por múltiples columnas
campañas_ordenadas = campañas.sort_values(
    ['conversion_rate', 'ctr'],
    ascending=[False, False]
)

# Reiniciar índice después de ordenar
campañas_ordenadas = campañas_ordenadas.reset_index(drop=True)

Comparación: Pandas vs Python puro

Python puro (trabajoso)

ventas = [
    {'producto': 'Laptop', 'precio': 800, 'cantidad': 2},
    {'producto': 'Mouse', 'precio': 25, 'cantidad': 10},
    {'producto': 'Teclado', 'precio': 60, 'cantidad': 5}
]

# Calcular total de cada venta
total_general = 0
for venta in ventas:
    total_venta = venta['precio'] * venta['cantidad']
    total_general += total_venta
    print(f"{venta['producto']}: ${total_venta}")

print(f"Total: ${total_general}")

Con Pandas (simple y rápido)

ventas_df = pd.DataFrame(ventas)
ventas_df['total'] = ventas_df['precio'] * ventas_df['cantidad']
print(ventas_df)
print(f"\nTotal: ${ventas_df['total'].sum()}")

Buenas prácticas

1. Explorar siempre primero

# Al recibir un DataFrame nuevo:
print(df.head())           # Ver primeros datos
print(df.info())           # Ver tipos y nulos
print(df.describe())       # Ver estadísticas
print(df.shape)            # Ver dimensiones

2. Usar nombres descriptivos

# ❌ Mal
df1 = pd.DataFrame(...)
df2 = df1[df1['col'] > 10]

# ✅ Bien
ventas_totales = pd.DataFrame(...)
ventas_altas = ventas_totales[ventas_totales['monto'] > 10000]

3. Evitar modificar DataFrames en bucles

# ❌ Mal (muy lento)
for i in range(len(df)):
    df.loc[i, 'total'] = df.loc[i, 'precio'] * df.loc[i, 'cantidad']

# ✅ Bien (operación vectorizada, ultra rápida)
df['total'] = df['precio'] * df['cantidad']

Ejercicio práctico

Crea un DataFrame con datos de redes sociales y analiza el engagement:

# Datos de posts en redes sociales
posts_df = pd.DataFrame({
    'fecha': ['2024-01-15', '2024-01-16', '2024-01-17', '2024-01-18', '2024-01-19'],
    'plataforma': ['Instagram', 'Facebook', 'LinkedIn', 'Instagram', 'Twitter'],
    'impresiones': [5000, 3000, 1500, 6000, 4000],
    'likes': [250, 180, 120, 400, 200],
    'comentarios': [25, 15, 30, 40, 18],
    'shares': [10, 8, 15, 20, 12]
})

# Tareas:
# 1. Calcular engagement rate: (likes + comentarios + shares) / impresiones * 100
# 2. Calcular engagement total por post
# 3. Encontrar el post con mejor engagement rate
# 4. Calcular promedio de engagement por plataforma

# Solución:
posts_df['engagement_total'] = posts_df['likes'] + posts_df['comentarios'] + posts_df['shares']
posts_df['engagement_rate'] = (posts_df['engagement_total'] / posts_df['impresiones']) * 100

print("Análisis de Engagement:")
print(posts_df[['plataforma', 'engagement_rate']].round(2))

mejor_post = posts_df.loc[posts_df['engagement_rate'].idxmax()]
print(f"\n🏆 Mejor post: {mejor_post['plataforma']} ({mejor_post['engagement_rate']:.2f}%)")

Resumen de la lección

Pandas es la librería esencial para análisis de datos en Python ✅ Series son arrays unidimensionales con índice (como columnas) ✅ DataFrames son tablas completas con filas y columnas ✅ Puedes crear DataFrames desde diccionarios, listas, CSV, Excel, SQL ✅ Operaciones matemáticas son vectorizadas (muy rápidas) ✅ Métodos como .describe(), .info(), .head() son esenciales para explorar datos


🎯 Próxima lección: 07. Carga y Exploración de Datos

En la siguiente lección aprenderás a cargar datos desde CSV, Excel, JSON y bases de datos. 🚀

¿Completaste esta lección?

Marca esta lección como completada. Tu progreso se guardará en tu navegador.