⚠ El trading implica un riesgo significativo de pérdida. Todo el contenido de este sitio es únicamente educativo y no constituye asesoramiento financiero.
Lección 3 de 13 · Gratis

Fundamentos de pandas: Series, DataFrames, el DatetimeIndex, selección y filtrado, y remuestreo de barras diarias a semanales

Comprende las Series y los DataFrames, indexa los datos de precios por fecha, selecciona filas con loc e iloc, filtra con máscaras booleanas y agrega barras diarias en barras semanales.

Autor: Moustafa HijaziContenido revisado: 2026-10-306 min de lecturaCurso de autoaprendizaje

Qué aprenderás

  • Qué son una Series y un DataFrame y por qué el DatetimeIndex es la columna vertebral del análisis de precios.
  • La diferencia entre loc, basado en etiquetas, e iloc, basado en posiciones, y cómo filtran filas las máscaras booleanas.
  • Cómo construir barras semanales o mensuales a partir de barras diarias con resample y la agregación correcta para cada columna.
  • Qué valores por defecto de pandas cambiaron en la versión 3.0 y cómo escribir código que se comporte igual en 2.2 y en 3.x.

Explicación

Una Series es un array unidimensional etiquetado: una columna de cierres con una fecha asociada a cada valor. Un DataFrame es una tabla de Series que comparten un mismo índice: apertura, máximo, mínimo, cierre y volumen uno al lado del otro. El índice contiene las etiquetas de las filas; para los datos de precios debería ser un DatetimeIndex, un índice especializado de marcas temporales que permite trocear por fechas, remuestrear y gestionar zonas horarias. Convención: import pandas as pd.

Crea un DataFrame con un diccionario de columnas y un índice de fechas:

idx = pd.bdate_range("2025-03-03", periods=10)

df = pd.DataFrame({"open": [...], "high": [...], "low": [...], "close": [...], "volume": [...]}, index=idx)

bdate_range genera solo días laborables y no sabe nada de los festivos bursátiles; los datos reales proceden de archivos (lección 4). Inspecciona con df.head(), df.info() (tipos y valores faltantes) y df.describe(). df.index.dtype debe mostrar datetime64; si muestra object, las fechas siguen siendo texto.

Selección. df["close"] devuelve una Series; df[["open", "close"]] (una lista) devuelve un DataFrame. df.loc[row_labels, columns] selecciona por etiqueta: df.loc["2025-03-05":"2025-03-07", "close"] da los cierres de esas tres fechas y, con loc, se incluyen ambos extremos del slice, a diferencia de las listas de Python. df.iloc[0:3] selecciona por posición entera (las tres primeras filas, excluido el final) y df.iloc[-1] es la última barra.

Filtrado. Una comparación sobre una Series produce una Series de booleanos, una máscara: up = df["close"] > df["open"]. Al pasar la máscara se seleccionan las filas que coinciden: df[up]. Combina máscaras con & (y), | (o) y ~ (no), cada condición entre sus propios paréntesis: df[(df["close"] > df["open"]) & (df["volume"] > 1200)]. up.sum() cuenta los valores True, y up.mean() es la proporción de días alcistas.

Añadir columnas es una asignación: df["range"] = df["high"] - df["low"]. Las operaciones están vectorizadas, es decir, se aplican a columnas enteras a la vez, y por eso pandas es rápido. shift(1) desplaza los valores una fila hacia abajo (el cierre de ayer en la fila de hoy) y pct_change() da las variaciones porcentuales; ambos dejan NaN (not a number, «no es un número») en la primera fila.

Remuestreo. resample agrupa las filas en intervalos de tiempo fijos. Cada columna necesita su propia regla: la apertura semanal es la primera apertura diaria, el máximo es el mayor valor, el mínimo el menor, el cierre el último y el volumen la suma:

rules = {"open": "first", "high": "max", "low": "min", "close": "last", "volume": "sum"}

weekly = df.resample("W-FRI").agg(rules)

El código "W-FRI" etiqueta cada semana con su viernes. Las barras mensuales usan "ME" (fin de mes). Los tutoriales antiguos escriben "M"; pandas 2.2 declaró obsoleto ese alias en favor de "ME" (igual que "QE" y "YE"), y el código escrito con los nuevos alias funciona tanto en 2.2 como en 3.x.

Cambios de pandas 3.0 que conviene conocer. Copy-on-Write (copia al escribir) es ahora el único modo: un DataFrame filtrado es una copia independiente, así que df[mask]["close"] = 0 nunca modifica df; escribe df.loc[mask, "close"] = 0. Las columnas de texto tienen ahora el dtype str en lugar de object.

Ejemplo práctico

Ejemplo hipotético: diez barras diarias del lunes 3 de marzo al viernes 14 de marzo de 2025, precios en euros, sin festivos.

Fecha Apertura Máximo Mínimo Cierre Volumen
03 mar 100 102 99 101 1,000
04 mar 101 104 100 103 1,200
05 mar 103 104 101 102 900
06 mar 102 105 101 104 1,100
07 mar 104 106 103 105 1,500
10 mar 105 106 103 104 1,300
11 mar 104 107 103 106 1,000
12 mar 106 108 105 107 1,400
13 mar 107 109 106 108 1,200
14 mar 108 110 106 107 1,600

El remuestreo da dos filas. Semana que termina el 7 de marzo: apertura = primera apertura = 100; máximo = max(102, 104, 104, 105, 106) = 106; mínimo = min(99, 100, 101, 101, 103) = 99; cierre = último cierre = 105; volumen = 1,000 + 1,200 + 900 + 1,100 + 1,500 = 5,700. Semana que termina el 14 de marzo: apertura 105, máximo 110, mínimo 103, cierre 107, volumen = 1,300 + 1,000 + 1,400 + 1,200 + 1,600 = 6,500.

Filtrado: (df["close"] > df["open"]).sum() devuelve 7, porque solo el 5, el 10 y el 14 de marzo cerraron por debajo de su apertura. df.loc["2025-03-05":"2025-03-07", "close"] devuelve 102, 104, 105.

Error frecuente

Confundir loc con iloc y olvidar que loc incluye el finaldf.iloc[0:5] devuelve cinco filas (posiciones 0 a 4), pero df.loc["2025-03-03":"2025-03-07"] devuelve todas las filas hasta el 7 de marzo inclusive. Usa iloc para «las N primeras» o «la última barra», y loc con fechas explícitas para los periodos.

Actividad práctica

Usando la tabla de diez barras anterior y trabajando en papel: (a) escribe la expresión de pandas que selecciona las barras del 10 al 12 de marzo inclusive; (b) indica qué devuelve df.iloc[-3:]["close"].tolist(); (c) calcula la única barra mensual que produciría df.resample("ME").agg(rules); (d) explica qué sale mal si alguien escribe df.resample("ME").last() para todas las columnas.

Mostrar solución

(a) df.loc["2025-03-10":"2025-03-12"], tres filas, ambos extremos incluidos.

(b) Los tres últimos cierres: [107, 108, 107].

(c) Una fila etiquetada el 31 de marzo de 2025 (fin de mes): apertura 100 (primera), máximo 110 (mayor), mínimo 99 (menor), cierre 107 (último), volumen 12,200 (5,700 + 6,500).

(d) .last() toma el valor final de cada columna: el mínimo mensual sería 106 en lugar de 99, la apertura 108 en lugar de 100 y el volumen 1,600 en lugar de 12,200. Pasa siempre las reglas por columna.

Limitaciones: el ejemplo no tiene festivos ni días faltantes; con datos reales, una semana con un festivo simplemente agrega cuatro barras, y aparece la etiqueta de mes «31 de marzo» aunque el último día de negociación fuera el 28 de marzo.

Ideas clave

  • Los datos de precios viven en un DataFrame con un DatetimeIndex; comprueba df.index.dtype antes que nada.
  • loc selecciona por etiqueta e incluye el final del slice; iloc selecciona por posición y lo excluye.
  • Las máscaras booleanas combinadas con &, | y ~ sustituyen a los bucles para filtrar, y .sum() sobre una máscara cuenta las coincidencias.
  • Remuestrea OHLCV con first/max/min/last/sum, usa los alias "W-FRI" y "ME", y recuerda el Copy-on-Write de pandas 3.0 al asignar.

Siguiente paso

La lección 4 introduce datos reales: leer archivos CSV y API gratuitas, entender los precios ajustados frente a los no ajustados, y gestionar los valores faltantes y las zonas horarias.

Autoevaluación

Responde a las preguntas y luego comprueba tus respuestas. Puedes volver a intentarlo tantas veces como quieras.

1. ¿Qué diccionario de agregación convierte correctamente barras OHLCV diarias en barras semanales?

2. Un DataFrame tiene 250 filas diarias. ¿Cuántas filas devuelven df.iloc[0:10] y df.loc['2025-01-02':'2025-01-15'] si el segundo rango contiene exactamente 10 días de negociación, incluidas ambas fechas extremas?

3. En pandas 3.0 ejecutas df[df['volume'] > 1000]['close'] = 0 y descubres que df no ha cambiado. ¿Por qué?

Autoevaluación automática para tu propio repaso. Tus respuestas se comprueban en tu navegador y no las vemos ni evaluamos. No es un examen ni una titulación.

Tu progreso

«Completada» solo significa que marcaste la lección como terminada. No es una prueba de tu comprensión. El progreso y las notas se guardan solo en este navegador y en este dispositivo, no en una cuenta.