Saltar al contenido
Volver al inicio 100 Días de Código en Python — Día 75: Google Trends y series de tiempo — remuestreo y gráficos que cuentan historias

100 Días de Código en Python — Día 75: Google Trends y series de tiempo — remuestreo y gráficos que cuentan historias

Nivel: Grado décimo Área: Tecnología e Informática Modalidad: Tutorial práctico Fuente: Curso "100 Days of Code: The Complete Python Pro Bootcamp" (Angela Yu, App Brewery). Contenido del Día 75 (nivel avanzado).

Este tutorial adapta pedagógicamente el Día 75. Las secciones 📝 Contenido original del curso provienen de las lecciones 550 a 558; el cuaderno de inicio y los 5 CSV están en los recursos del curso. En algunas lecciones parte del código aparece solo en imágenes; aquí se reconstruye y se verifica. Los retos 🟢🟡🟠🔴, las secciones sobre correlación y causalidad y gráficos honestos, el proyecto extra y el proyecto integrador del bloque de datos (Días 72 a 75) son creaciones de esta adaptación. Las correcciones al material original aparecen como 🛠️ Nota técnica.

Nota sobre las verificaciones: el 27 de septiembre de 2026, con Python 3.14, pandas 3.0.6, Matplotlib 3.11.2 y una copia pública de los 5 CSV del curso (publicada en GitHub por otro estudiante del mismo curso), se ejecutó todo el código. Las dimensiones y valores coinciden con el curso (124, 181, 2204 y 73 filas; búsquedas de Tesla entre 2 y 31), con tres diferencias importantes: resample('M') ya no funciona en pandas 3 (ValueError: 'M' is no longer supported for offsets. Please use 'ME' instead.); los "2 valores faltantes" del precio de Bitcoin son una sola fila (4 de agosto de 2020) con dos celdas vacías; y el pico anual de búsquedas de "unemployment benefits" cae en enero en 12 de los 16 años completos, no en diciembre.


Tabla de contenidos

  1. Antes de empezar: ¿qué nos dicen las búsquedas?
  2. Explorar los datos de Google Trends
  3. Limpiar y convertir fechas
  4. Remuestrear: de diario a mensual
  5. Tesla: estilo paso a paso
  6. Localizadores y formatos de fecha
  7. Bitcoin: estilos de línea y marcadores
  8. Desempleo: cuadrículas, estacionalidad y media móvil
  9. El efecto de los datos nuevos: 2020
  10. 📖 Correlación no es causalidad
  11. 🚀 Proyecto del día: tres historias con Google Trends
  12. 🌟 Proyecto extra: ¿qué busca Colombia?
  13. 🏆 Proyecto integrador del bloque de datos (Días 72 a 75)
  14. 🧩 Comprueba lo aprendido
  15. 🤖 Programar con apoyo de IA
  16. 🛠️ Correcciones técnicas al material original
  17. 📋 Matriz de trazabilidad
  18. 📦 Evidencias de aprendizaje del Día 75

0. Antes de empezar: ¿qué nos dicen las búsquedas?

(Fuente: 550-day-75-goals-what-you-will-make-by-the-end-of-the-day.md)

📝 Contenido original del curso

Google Trends da acceso a la popularidad de los términos de búsqueda de Google. Investigaremos:

  • cómo se relaciona el volumen de búsqueda de "Bitcoin" con su precio;
  • cómo se relaciona el de una acción muy comentada, Tesla, con el precio de esa acción;
  • cómo varían las búsquedas de "Unemployment Benefits" (subsidio de desempleo) con la tasa de desempleo real de Estados Unidos.

Aprenderás a hacer comparables series de tiempo remuestreándolas a la misma periodicidad (de diario a mensual); a afinar el estilo de los gráficos con límites, etiquetas, estilos de línea, marcadores, colores y resolución; a usar cuadrículas para ver la estacionalidad; a encontrar y ubicar valores NaN; y a usar localizadores para el eje del tiempo. También repasarás lo de los tres días anteriores.

Preparación: descarga el ZIP, sube el cuaderno a Google Drive y agrega los 5 CSV.

Prerequisitos: exploración y limpieza (Día 72), fechas, pivote y media móvil (Día 73), dos ejes y agg (Día 74).


(Fuente: 551-data-exploration-making-sense-of-google-search-data.md)

📝 Contenido original del curso

El cuaderno ya importa las bibliotecas y crea cuatro DataFrames. Reto: para df_tesla, df_unemployment y los dos de Bitcoin: ¿forma?, ¿filas y columnas?, ¿nombres de columnas?, ¿el mayor número en la columna de búsqueda? (prueba .describe()), ¿periodicidad (diaria, semanal, mensual)?

Solución:

  • Tesla: 124 filas y 3 columnas (mes, popularidad de búsqueda y precio de cierre de la acción). La búsqueda va de 2 a 31.
  • Desempleo: 181 filas y 3 columnas, mensual desde 2004; el máximo de búsqueda es 100.
  • Bitcoin: un CSV con el precio de cierre diario y el volumen (2204 filas) y otro con la búsqueda mensual.

.describe() es "una de mis funciones favoritas": da estadísticas descriptivas de inmediato.

¿Qué significan los números de búsqueda? Google no publica el volumen real. Según su definición: "los números representan el interés de búsqueda relativo al punto más alto del gráfico para la región y el periodo. 100 es la máxima popularidad; 50, la mitad; 0, que no hubo datos suficientes". Cada dato se divide por el total de búsquedas de esa región y periodo y luego se escala para que el máximo sea 100. No dice cuántas búsquedas hubo, pero es una buena aproximación.

Parámetros usados para generar los datos:

  • "Tesla", mundial, búsqueda web.
  • "Bitcoin", mundial, búsqueda de noticias.
  • "Unemployment Benefits", Estados Unidos, búsqueda web.

📖 Resultados verificados

DataFrame Forma Columnas Primer dato
df_tesla (124, 3) MONTH, TSLA_WEB_SEARCH, TSLA_USD_CLOSE 2010-06-01
df_btc_search (73, 2) MONTH, BTC_NEWS_SEARCH 2014-09
df_btc_price (2204, 3) DATE, CLOSE, VOLUME 2014-09-17
df_unemployment (181, 3) MONTH, UE_BENEFITS_WEB_SEARCH, UNRATE 2004-01

La consecuencia más importante de la escala 0–100: un 31 para Tesla y un 31 para Bitcoin no son comparables: cada serie está escalada respecto a su propio máximo. En este archivo Tesla nunca llega a 100 (su máximo es 31), lo que indica que el 100 de esa consulta quedó fuera de las filas que tenemos (por ejemplo, en un periodo o un término distinto); los datos no permiten saber cuál. Y si descargas los datos otro día, todos los valores pueden cambiar.


2. Limpiar y convertir fechas

(Fuente: 552-data-cleaning-resampling-time-series-data.md, primera parte)

📝 Contenido original del curso

Reto: ¿hay valores faltantes en los 4 DataFrames? Si sí, ¿cuántos y en qué fila? Elimina esas filas.

Solución:

Python
print(f'Missing values for Tesla?: {df_tesla.isna().values.any()}')
print(f'Missing values for U/E?: {df_unemployment.isna().values.any()}')
print(f'Missing values for BTC Search?: {df_btc_search.isna().values.any()}')

Tres no tienen faltantes; el del precio de Bitcoin sí: .sum() cuenta los True y da 2. Para ubicarlos, un subconjunto con .isna(); para quitarlos, .dropna() (con inplace=True o asignando).

Reto: convertir a fechas las columnas MONTH y DATE de los 4 DataFrames y comprobarlo:

Python
df_tesla.MONTH = pd.to_datetime(df_tesla.MONTH)
df_btc_search.MONTH = pd.to_datetime(df_btc_search.MONTH)
df_unemployment.MONTH = pd.to_datetime(df_unemployment.MONTH)
df_btc_price.DATE = pd.to_datetime(df_btc_price.DATE)

📖 Resultados verificados

Python
df_btc_price.isna().values.sum()        # 2
df_btc_price[df_btc_price.CLOSE.isna()]
#             DATE  CLOSE  VOLUME
# 2148  2020-08-04    NaN     NaN

🛠️ Nota técnica (verificado): hay 2 celdas vacías, pero en una sola fila: el 4 de agosto de 2020 no tiene ni precio ni volumen. isna().values.sum() cuenta celdas; para contar filas con algún faltante: df_btc_price.isna().any(axis=1).sum() (da 1). Después de dropna() quedan 2203 filas.


3. Remuestrear: de diario a mensual

(Fuente: 552-data-cleaning-resampling-time-series-data.md, segunda parte)

🎯 Objetivo de aprendizaje

Convertir una serie diaria en una mensual para compararla con otra, eligiendo cómo resumir cada mes.

📝 Contenido original del curso

El precio de Bitcoin es diario y su búsqueda es mensual. Para compararlos, .resample() cambia la frecuencia: se indica la columna de fechas y la regla ('M' mensual; otras: 'Y' anual, 'T' minuto). Luego se decide cómo resumir: queremos el último precio del mes (el cierre de mes):

Python
df_btc_monthly = df_btc_price.resample('M', on='DATE').last()
# el promedio del mes sería: df_btc_price.resample('M', on='DATE').mean()

Resultado: 73 filas, igual que los datos de búsqueda.

📖 Explicación conceptual (verificada con pandas 3.0.6)

🛠️ Nota técnica (verificado): en pandas 3, resample('M', ...) falla:

Texto
ValueError: Invalid frequency: M. ... 'M' is no longer supported for offsets. Please use 'ME' instead.

Los alias cambiaron para ser más claros: 'ME' = fin de mes (month end), 'MS' = inicio de mes, 'YE' = fin de año (antes 'Y'), 'min' = minuto (antes 'T'), 'h' = hora. La línea correcta es:

Python
df_btc_monthly = df_btc_price.resample('ME', on='DATE').last()

Resultados verificados: 73 filas; el índice son fechas de fin de mes (2014-09-30, 2014-10-31…), mientras que df_btc_search.MONTH usa el primer día (2014-09-01…). Son los mismos 73 meses (comprobado con to_period('M')), así que se pueden graficar juntos.

last() o mean(): en el último mes, el precio de cierre fue 10 912,5 y el promedio del mes 10 655,7. Ninguno es "el correcto": depende de la pregunta. El precio de cierre es el que ve un inversionista a fin de mes; el promedio representa mejor todo el mes y es menos sensible a un día raro.

Resumen Método Cuándo
Último valor .last() Precios de cierre, saldos
Promedio .mean() Temperaturas, tasas
Total .sum() Ventas, lluvias, visitas
Máximo .max() Picos (por ejemplo, contaminación)

Retos adicionales (creados para esta adaptación)

  • 🟢 Reto 1: remuestrea el precio de Bitcoin por semana ('W') y por año ('YE'). ¿Cuántas filas tiene cada uno?
  • 🟡 Reto 2: remuestrea el volumen con .sum() y el precio con .last() en una sola operación (.agg({'CLOSE': 'last', 'VOLUME': 'sum'})).
  • 🟠 Reto 3: grafica en el mismo eje el cierre mensual y el promedio mensual. ¿En qué meses se separan más? ¿Qué pasó esos meses?

4. Tesla: estilo paso a paso

(Fuente: 553-data-visualisation-tesla-line-charts-in-matplotlib.md)

📝 Contenido original del curso

Reto 1: precio de Tesla contra búsqueda, con dos ejes (repaso del Día 74):

Python
ax1 = plt.gca()
ax2 = ax1.twinx()
ax1.set_ylabel('TSLA Stock Price')
ax2.set_ylabel('Search Trend')
ax1.plot(df_tesla.MONTH, df_tesla.TSLA_USD_CLOSE)
ax2.plot(df_tesla.MONTH, df_tesla.TSLA_WEB_SEARCH)

Reto 2: colores: un azul con nombre ('skyblue') para la búsqueda y un rojo en hexadecimal ('#E6232E') para el precio, en las líneas y en las etiquetas de los ejes.

Reto 3: tamaño 14 × 8; fuentes de 14 en las etiquetas y el eje x; texto del eje x rotado 45°; título "Tesla Web Search vs Price"; líneas más gruesas; más resolución (DPI); límites en los ejes (set_xlim, set_ylim); y plt.show() para mostrar el gráfico de forma explícita (importante fuera de los cuadernos).

Solución final:

Python
plt.figure(figsize=(14, 8), dpi=120)
plt.title('Tesla Web Search vs Price', fontsize=18)
plt.xticks(fontsize=14, rotation=45)

ax1 = plt.gca()
ax2 = ax1.twinx()

ax1.set_ylabel('TSLA Stock Price', color='#E6232E', fontsize=14)
ax2.set_ylabel('Search Trend', color='skyblue', fontsize=14)

ax1.set_ylim([0, 600])
ax1.set_xlim([df_tesla.MONTH.min(), df_tesla.MONTH.max()])

ax1.plot(df_tesla.MONTH, df_tesla.TSLA_USD_CLOSE, color='#E6232E', linewidth=3)
ax2.plot(df_tesla.MONTH, df_tesla.TSLA_WEB_SEARCH, color='skyblue', linewidth=3)

plt.show()

Los límites pueden ser fijos (0 a 600 dólares) o calculados con .min() y .max(). Si aparece una advertencia de Matplotlib sobre el convertidor de fechas, no es un error: se resuelve registrando los convertidores de pandas, como indica la advertencia.

📖 Explicación conceptual (adaptación)

plt contra ax: con un solo eje, plt.plot, plt.ylabel… funcionan sobre "el eje actual". Con dos ejes, es más claro trabajar con los objetos ax1 y ax2 (ax1.set_ylabel, ax1.set_xlim), porque así sabes exactamente a cuál afecta cada instrucción. Fíjate en que el nombre cambia: plt.ylabel → ax.set_ylabel.

💡 Resolución: dpi=120 con figsize=(14, 8) produce una imagen de 1680 × 960 píxeles. Para un informe impreso, guarda con plt.savefig('tesla.png', dpi=200, bbox_inches='tight').

🛠️ Nota técnica: en los datos (verificado), el precio máximo de Tesla es 498,32 dólares y el pico de búsqueda (31) es de septiembre de 2020. Los precios de acciones históricos suelen venir ajustados por las divisiones de acciones (splits): si comparas con el precio actual de Tesla en Internet, las cifras no coincidirán, porque la acción se dividió otra vez después de 2020.


5. Localizadores y formatos de fecha

(Fuente: 554-using-locators-and-dateformatters-to-generate-tick-marks-on-a-time-line.md)

📝 Contenido original del curso

Las marcas del eje del tiempo suelen quedar mal. Los localizadores de matplotlib.dates ayudan:

Python
import matplotlib.dates as mdates

years = mdates.YearLocator()                # una marca principal por año
months = mdates.MonthLocator()              # una marca secundaria por mes
years_fmt = mdates.DateFormatter('%Y')      # mostrar solo el año

ax1.xaxis.set_major_locator(years)
ax1.xaxis.set_major_formatter(years_fmt)
ax1.xaxis.set_minor_locator(months)

Con las marcas se puede fechar el pico de interés de marzo de 2016, cuando se presentó el Tesla Model 3. Y los picos más recientes no coinciden con un auto nuevo, sino con el precio disparado de la acción.

📖 Explicación conceptual (verificada)

  • Marcas principales (major): las que llevan texto (cada año).
  • Marcas secundarias (minor): rayitas sin texto (cada mes), que ayudan a ubicar un punto.
  • DateFormatter usa los mismos códigos que strftime (Día 32): '%Y' año, '%b %Y' "Mar 2016", '%m/%Y' "03/2016".

Si en lugar de "Mar" quieres "mar." (en español), el resultado depende de la configuración del sistema; es más predecible usar números ('%m/%Y').


6. Bitcoin: estilos de línea y marcadores

(Fuente: 555-data-visualisation-bitcoin-line-style-and-markers.md)

📝 Contenido original del curso

Copia la celda de Tesla y modifícala:

  1. Título "Bitcoin News Search vs Resampled Price".
  2. Eje y: "BTC Price".
  3. Límites de los ejes más adecuados.
  4. El precio como línea discontinua (linestyle).
  5. Los datos de búsqueda con círculos (marker).
  6. ¿Los grandes aumentos de búsquedas vinieron con grandes aumentos de precio?
Python
ax1.set_ylim(bottom=0, top=15000)
ax1.set_xlim([df_btc_monthly.index.min(), df_btc_monthly.index.max()])

ax1.plot(df_btc_monthly.index, df_btc_monthly.CLOSE,
         color='#F08F2E', linewidth=3, linestyle='--')
ax2.plot(df_btc_monthly.index, df_btc_search.BTC_NEWS_SEARCH,
         color='skyblue', linewidth=3, marker='o')

El truco: las fechas de la serie mensual están en el índice: df_btc_monthly.index. Los movimientos locos de precio de comienzos de 2018 coincidieron con búsquedas récord ("todo el mundo hablaba de Bitcoin, y lo compraba"). En el primer trimestre de 2019 hubo otro gran salto de precio, pero con mucho menos aumento de búsquedas ("quizá porque ya todo el mundo sabía qué era Bitcoin").

📖 Resultados verificados y detalles

  • El máximo mensual del precio de cierre es de diciembre de 2017 (≈ 14 156 dólares) y la búsqueda máxima (100) también es de diciembre de 2017: por eso el límite superior de 15 000 del curso es adecuado.
  • df_btc_monthly.index y df_btc_search.BTC_NEWS_SEARCH se grafican juntos porque tienen el mismo número de filas en el mismo orden (73 meses). Si una serie tuviera un mes de más, las líneas quedarían corridas sin ningún error. Más seguro: usar para cada línea sus propias fechas (df_btc_search.MONTH).
Estilo de línea Código
Continua '-'
Discontinua (rayas) '--'
Raya y punto '-.'
Punteada ':'

🛠️ Nota técnica: el resumen del curso llama "punteada" (dotted) a '-.'; en realidad es raya y punto. La línea punteada es ':'.

💡 Precaución sobre Bitcoin: este análisis describe cómo se movieron las búsquedas y el precio en el pasado; no sirve para predecir precios ni para decidir inversiones (sección 9).


7. Desempleo: cuadrículas, estacionalidad y media móvil

(Fuente: 556-data-visualisation-unemployment-how-to-use-grids.md)

📝 Contenido original del curso

Reto: búsquedas de "unemployment benefits" contra la tasa oficial de desempleo (de la FRED, la base de datos de la Reserva Federal de San Luis): título, etiqueta "FRED U/E Rate", límites, y una cuadrícula gris de líneas discontinuas. ¿Hay estacionalidad en las búsquedas?

Python
ax1.grid(color='grey', linestyle='--')

Las líneas verticales de la cuadrícula coinciden con los picos de búsqueda: "muchos picos son a fin de año, en diciembre", lo que muestra estacionalidad en el mercado laboral. La crisis financiera de 2007/2008 disparó el desempleo, que tardó unos 10 años (2007–2017) en volver al nivel anterior. Curiosamente, el gran pico de búsquedas de finales de 2013 no vino con un aumento del desempleo: "algo más estaba pasando".

Reto: la media móvil de 3 o 6 meses de las búsquedas. ¿Qué línea se mueve primero?

Python
roll_df = df_unemployment[['UE_BENEFITS_WEB_SEARCH', 'UNRATE']].rolling(window=6).mean()

Las búsquedas suben antes que la tasa oficial y bajan antes: funcionan como un indicador adelantado, mientras que la tasa de desempleo es un indicador rezagado.

📖 Resultados verificados

  • La búsqueda máxima (100) es de febrero de 2009, con desempleo de 8,3 %; el desempleo máximo del periodo 2004–2019 es 10,0 %, en octubre de 2009: las búsquedas tocaron techo meses antes que el desempleo, como dice el curso.
  • La estacionalidad: en los 16 años completos, el mes con más búsquedas fue enero en 12 años, diciembre en 2, y febrero y julio en 1 cada uno.

🛠️ Nota técnica (verificado): la estacionalidad existe, pero el pico es mayoritariamente enero, no diciembre. Las líneas verticales de la cuadrícula están en el 1 de enero de cada año (el localizador de años), y los picos caen justo ahí. Una explicación plausible: muchos empleos temporales de fin de año terminan en diciembre y la gente busca el subsidio en enero. Lección: comprueba con los datos lo que el gráfico parece decir (Reto 1).

Retos adicionales (creados para esta adaptación)

  • 🟢 Reto 1: calcula el promedio de búsquedas por mes del año (df.groupby(df.MONTH.dt.month).UE_BENEFITS_WEB_SEARCH.mean()) y grafícalo en barras. ¿Qué mes gana?
  • 🟡 Reto 2: mide el "adelanto": desplaza la serie de búsquedas con .shift(n) y calcula la correlación con el desempleo (.corr()) para n de 0 a 12 meses. ¿Con qué desplazamiento la correlación es mayor?
  • 🟠 Reto 3: investiga qué pasó a finales de 2013 en Estados Unidos con los subsidios de desempleo (pista: busca "emergency unemployment compensation 2013") y escribe una anotación en el gráfico con ax.annotate.

8. El efecto de los datos nuevos: 2020

(Fuentes: 557-data-visualisation-unemployment-the-effect-of-new-data.md y 558-learning-points-y-summary.md)

📝 Contenido original del curso

Reto: leer 'UE Benefits Search vs UE Rate 2004-20.csv', convertir las fechas y graficar. ¿Qué se ve?

Python
df_ue_2020 = pd.read_csv('UE Benefits Search vs UE Rate 2004-20.csv')
df_ue_2020.MONTH = pd.to_datetime(df_ue_2020.MONTH)

"No es bonito": el desempleo en Estados Unidos se disparó a niveles sin precedentes durante la pandemia de COVID, eclipsando los de la crisis financiera. "Esperemos que la recuperación sea más rápida esta vez".

Resumen del día: .describe(); .resample(); localizadores de matplotlib.dates; contar NaN con .isna().values.sum(); dpi; estilos '--' y '-.'; marcadores ('o', '^'); límites, etiquetas, grosor y colores (con nombre y hexadecimales); .grid() para la estacionalidad.

📖 Resultados verificados y reflexión

El archivo con 2020 tiene 200 filas (hasta agosto de 2020); el desempleo máximo es 14,7 % en abril de 2020, frente al 10,0 % de 2009.

Por qué importa: los datos nuevos no solo agregan puntos, pueden cambiar la escala y la historia. En el gráfico de 2004–2019, la crisis de 2008 parece enorme; con 2020, se ve pequeña. Además, como Google Trends escala a 100 el máximo del periodo, el pico de búsquedas de 2020 reescala todos los valores anteriores: los "100" de 2009 dejan de serlo. Compara las dos versiones del CSV (Reto 3 del proyecto).


9. 📖 Correlación no es causalidad

(Sección creada para esta adaptación.)

Tres gráficos del día muestran dos líneas que se mueven "juntas". Eso se llama correlación. Pero:

Afirmación ¿Qué muestran los datos?
"Las búsquedas de Bitcoin hacen subir el precio" Solo que coinciden. Podría ser al revés (el precio sube → salen noticias → la gente busca), o ambos causados por otra cosa
"Buscar 'unemployment benefits' predice el desempleo" Que en el pasado subió antes. Es útil como pista, pero puede fallar (el pico de 2013)
"Si Tesla aparece en las noticias, su acción sube" Los picos coinciden a veces (Model 3 en 2016) y otras no

Además, las escalas de dos ejes se pueden ajustar para que cualquier par de líneas parezca relacionado (Día 74). Por eso, antes de concluir:

  1. Calcula la correlación con números (.corr()), no solo "a ojo".
  2. Busca una explicación que tenga sentido y ponla a prueba.
  3. Revisa si se cumple en otros periodos o lugares.
  4. Nunca uses un gráfico así para tomar decisiones de dinero (criptomonedas, acciones): el pasado no garantiza el futuro.

(Integra las lecciones 551 a 558.)

Problema

¿Las búsquedas en Internet reflejan lo que pasa en el mundo real? Tres casos: una acción, una criptomoneda y el desempleo.

Objetivo

Un cuaderno con los cuatro gráficos del curso (Tesla, Bitcoin, desempleo y desempleo con 2020), bien presentados, y conclusiones prudentes.

Requisitos funcionales

  1. Exploración de los 4 DataFrames con shape, columns y describe().
  2. Detección y eliminación de faltantes; fechas convertidas.
  3. Remuestreo del precio de Bitcoin a mensual con 'ME'.
  4. Gráficos con dos ejes, colores, título, límites, DPI, localizadores de fecha, estilos de línea, marcadores y cuadrícula donde corresponda.
  5. Media móvil de 6 meses para el desempleo.
  6. La comparación 2004–2019 contra 2004–2020.
  7. Una sección de conclusiones que distinga correlación y causalidad.

Restricciones técnicas

  • Compatible con pandas 3 ('ME', no 'M').
  • Cada línea graficada con sus propias fechas.
  • Todos los gráficos guardados en PNG.

Planificación

  1. Comprender qué es Google Trends. 2. Entradas: 5 CSV. 3. Procesos: explorar → limpiar → convertir → remuestrear → graficar → suavizar → comparar. 4. Salidas: 4 gráficos y conclusiones. 5. Una sección por lección. 6. Bocetar los gráficos. 7. Implementar. 8. Verificar con la tabla de pruebas. 9. Corregir. 10. Concluir.

Construcción paso a paso

  • Versión 1: exploración y limpieza.
  • Versión 2: remuestreo.
  • Versión 3: Tesla con todo el estilo.
  • Versión 4: Bitcoin.
  • Versión 5: desempleo con cuadrícula y media móvil.
  • Versión final: 2020 y conclusiones.

Pruebas

Comprobación Valor esperado (verificado)
Formas Tesla (124, 3), desempleo (181, 3), BTC precio (2204, 3), BTC búsqueda (73, 2)
Celdas faltantes en el precio de BTC 2 (en 1 fila: 2020-08-04)
Filas del precio mensual 73
Mes de máxima búsqueda de Bitcoin Diciembre de 2017 (100)
Desempleo máximo 2004–2019 / 2004–2020 10,0 % (oct. 2009) / 14,7 % (abr. 2020)

🧪 Prueba y depuración

Python
df_btc_monthly = df_btc_price.resample('M', on='DATE').last()
plt.figure(figsize=(14, 8), dpi=120)
ax1 = plt.gca()
ax2 = ax1.twinx()
ax1.ylabel('BTC Price')
ax1.plot(df_btc_price.DATE, df_btc_monthly.CLOSE, linestyle='dotted')
ax2.plot(df_btc_monthly.index, df_btc_search.BTC_NEWS_SEARCH, marker='circle')

Encuentra cinco problemas: 'M' falla en pandas 3 ('ME'); ax1.ylabel no existe (es ax1.set_ylabel); se grafican 2203 fechas diarias contra 73 precios mensuales (ValueError por tamaños distintos); linestyle='dotted' funciona, pero marker='circle' no es válido (es 'o'); y el gráfico no tiene título ni límites.

⭐ Extensión del proyecto

  • Reto 1: calcula la correlación entre búsqueda y precio para Tesla y para Bitcoin. ¿Cuál es más alta?
  • Reto 2: repite el gráfico de Bitcoin con el promedio mensual (.mean()) en lugar del cierre. ¿Cambia la conclusión?
  • Reto 3: compara los valores de búsqueda del mismo mes en los archivos 2004–19 y 2004–20. ¿Son iguales? ¿Por qué?

11. 🌟 Proyecto extra: ¿qué busca Colombia?

(Proyecto creado para esta adaptación; no existe en el curso original.)

Situación

¿Las búsquedas de los colombianos reflejan su calendario? Por ejemplo, "ICFES" o "Saber 11" antes de la prueba, "uniformes" antes del regreso a clases, "lluvias" en temporada invernal.

Requisitos

  1. En trends.google.com, elige dos términos relacionados con tu vida escolar o tu región, con Colombia como región y un periodo de al menos 5 años. Descarga el CSV (botón de descarga del gráfico).
  2. Límpialo: las primeras filas del CSV de Google Trends suelen ser encabezados descriptivos (skiprows), y los valores "<1" deben convertirse.
  3. Remuestrea si hace falta y grafica con localizadores de fecha, cuadrícula y una anotación en cada pico.
  4. Calcula el promedio por mes del año y responde: ¿en qué mes se busca más cada término? ¿Coincide con lo que esperabas?
  5. Compara con un dato oficial si existe (por ejemplo, las fechas de la prueba Saber 11 publicadas por el ICFES).

Decisiones que debes tomar (y justificar)

  • ¿Qué periodo eliges y por qué afecta la escala 0–100?
  • ¿Qué dirías a alguien que concluye "la gente buscó más 'ICFES' en 2021, así que hubo más estudiantes"?

Casos de prueba

  • Tras la limpieza, la columna de búsqueda es numérica (dtype entero o decimal) y sin NaN inesperados.
  • El gráfico tiene título, ejes, fuente de los datos y fecha de descarga.

12. 🏆 Proyecto integrador del bloque de datos (Días 72 a 75)

(Proyecto creado para esta adaptación. Se construyó por etapas desde el Día 72. El curso continúa con más análisis de datos hasta el Día 81; este integrador reúne lo aprendido en los Días 72 a 75.)

Situación problema

En el colegio y en el municipio se toman decisiones (dónde poner una ciclovía, cuándo programar las jornadas de salud, cómo reducir la deserción) muchas veces sin mirar los datos, aunque existen datos abiertos públicos que podrían ayudar.

Contexto

Colombia publica miles de conjuntos de datos abiertos en datos.gov.co. Con pandas y Matplotlib, un grupo de estudiantes puede convertirlos en información útil… si trabaja con rigor: limpiar bien, graficar con honestidad y no confundir correlación con causalidad.

Pregunta orientadora

¿Qué puede aprender nuestra comunidad educativa a partir de los datos abiertos sobre un tema que nos afecta, y cómo comunicarlo de forma clara y honesta?

Objetivo

Construir el Observatorio de Datos del Colegio: un cuaderno de análisis, bien documentado, que responda tres preguntas sobre un tema de la comunidad con datos abiertos, y un informe de una página para la comunidad.

Requerimientos

Funcionales

  1. Exploración y limpieza (Día 72): función diagnostico(df); faltantes y datos basura tratados y documentados.
  2. Series de tiempo (Días 73 y 75): fechas convertidas; remuestreo a una frecuencia común; media móvil donde ayude; gráfico de líneas con localizadores de fecha.
  3. Agregación y combinación (Día 74): al menos dos conjuntos de datos unidos con merge; resúmenes con groupby y agregación con nombre.
  4. Visualización (Días 73 a 75): mínimo cuatro gráficos de al menos tres tipos distintos (líneas, barras, dispersión; dos ejes solo si se justifica), todos con título, ejes, unidades, fuente y leyenda cuando corresponda.
  5. Estacionalidad o tendencia (Día 75): identificar y comprobar con números un patrón en el tiempo.
  6. Conclusiones para cada pregunta, separando lo que los datos muestran de lo que no pueden mostrar.

No funcionales

  • Reproducibilidad: el cuaderno funciona con Reiniciar y ejecutar todo; los datos están en una carpeta data/ con un FUENTES.md (URL, fecha de descarga, licencia).
  • Compatibilidad: código que funcione con pandas 3 ('ME', numeric_only=True, .loc en lugar de posiciones).
  • Accesibilidad: colores con contraste suficiente (Día 65), sin depender solo del color, fuentes legibles.
  • Ética: ningún dato que permita identificar a personas; datos del colegio solo agregados y con autorización.

Restricciones

  • Fuentes abiertas y citadas (datos.gov.co, DANE, IDEAM, ICFES, Google Trends u otras oficiales).
  • Nada de conclusiones causales sin justificación.
  • El informe para la comunidad cabe en una página y usa como máximo dos gráficos.

Etapas de desarrollo

Etapa Día Producto
1. Tema, preguntas y primer conjunto de datos 72 diagnostico(df), descripción de los datos en Markdown
2. Fechas y primeros gráficos 73 Dos gráficos de líneas con estilo completo
3. Combinar datos y agregar 74 merge con un segundo conjunto, agg con nombre, barras y dispersión
4. Series de tiempo e informe 75 Remuestreo, estacionalidad comprobada, conclusiones e informe de una página

Etapa 4 (hoy)

  1. Remuestrea tus series a una frecuencia común y busca un patrón estacional o una tendencia; compruébalo con un groupby por mes o con .corr().
  2. Revisa todos tus gráficos con la lista de verificación de abajo.
  3. Escribe las conclusiones y el informe de una página para la comunidad (por ejemplo, para el consejo estudiantil o la rectoría).

Entregables

  1. La carpeta del proyecto: observatorio.ipynb, data/, FUENTES.md y README.md (cómo ejecutarlo).
  2. El informe de una página (PDF o impreso).
  3. Una presentación de 5 minutos: la pregunta, un gráfico clave, la conclusión y una limitación.
  4. El cuaderno de errores del bloque (al menos 10 entradas).

Casos de prueba (lista de verificación)

# Comprobación
1 Reiniciar y ejecutar todo termina sin errores
2 Cada conjunto de datos tiene su fila en FUENTES.md
3 diagnostico() se ejecuta para cada DataFrame antes de analizarlo
4 Ningún gráfico incluye un periodo incompleto sin advertirlo
5 Todos los gráficos tienen título, ejes, unidades y fuente
6 El merge reporta cuántas filas se perdieron o duplicaron
7 El patrón temporal se confirma con un cálculo, no solo "a ojo"
8 Las conclusiones no afirman causalidad sin justificación
9 No hay datos que identifiquen a personas

Criterios técnicos de funcionamiento

Criterio Nivel básico Nivel alto
Limpieza Elimina faltantes Documenta cada decisión (qué, por qué, cuántas filas) y compara antes y después
Transformación Usa groupby y pivot Remuestreo, agregación con nombre, merge con el how justificado
Visualización Gráficos correctos Gráficos honestos, legibles y accesibles, cada uno responde a una pregunta
Análisis Describe los datos Cuantifica patrones (correlación, estacionalidad) y discute limitaciones
Reproducibilidad El cuaderno funciona Otro estudiante lo ejecuta con el README y obtiene los mismos resultados
Comunicación Informe con resultados Informe de una página claro para personas sin formación técnica

Posibles extensiones

  • Continuar con los Días 76 a 81 del curso: gráficos interactivos con Plotly, NumPy, regresión lineal con seaborn y un modelo para predecir.
  • Publicar el informe como página web con Flask (bloque web) o como cuaderno en GitHub (Día 70).
  • Actualizar el análisis automáticamente cada mes descargando los datos con requests (Día 33).

13. 🧩 Comprueba lo aprendido

Conceptuales

  1. ¿Qué significa un valor de 50 en Google Trends? ¿Por qué no se pueden comparar directamente dos términos descargados por separado?
  2. ¿Qué hace resample() y por qué hace falta aquí?
  3. ¿Cuándo resumirías un mes con .last() y cuándo con .mean()?
  4. ¿Qué es la estacionalidad? ¿Qué herramienta del gráfico ayuda a verla?
  5. ¿Qué es un indicador adelantado? Da el ejemplo del día.

Análisis de código

Python
df_btc_price.resample('ME', on='DATE').agg({'CLOSE': 'last', 'VOLUME': 'sum'}).head(2)

¿Qué tabla produce? ¿Qué representa cada columna?

Predicción

Si remuestreas los 2203 días de precio de Bitcoin por año ('YE'), ¿cuántas filas obtienes? (Pista: los datos van de septiembre de 2014 a 2020.)

Depuración

"Mi gráfico de Bitcoin muestra la línea del precio corrida un mes respecto a la de búsquedas". ¿Qué pudo pasar?

Modificación

Cambia el gráfico del desempleo para que marque con un triángulo ('^') el mes de mayor búsqueda de cada año.

Creación

Escribe una función grafico_dos_ejes(fechas, serie1, serie2, titulo, etiqueta1, etiqueta2) que dibuje el gráfico con dos ejes, colores, localizadores y cuadrícula, y úsala para los tres casos del día.


14. 🤖 Programar con apoyo de IA

Ciclo de trabajo: formula el problema → inténtalo tú → consulta a la IA → lee y entiende → prueba → compara con la documentación oficial → modifica → explica con tus palabras.

Actividad 1 — Alias de frecuencia. Pide a una IA el código para pasar datos diarios a mensuales con pandas. Si usa 'M', ejecútalo en pandas 3 y consulta la tabla de alias de la guía de usuario de pandas (Time series / date functionality, sección de offset aliases).

Actividad 2 — ¿Causalidad? Muestra a una IA el gráfico de búsquedas de Bitcoin contra el precio y pregúntale si las búsquedas "hacen subir" el precio. ¿Distingue correlación de causalidad? Compara con la sección 9.

Actividad 3 — Verificar una afirmación del curso. Pregunta a una IA en qué mes hay más búsquedas de "unemployment benefits" en Estados Unidos. Comprueba con los datos (Reto 1 de la sección 7) y anota si la IA, el curso y los datos coinciden.


15. 🛠️ Correcciones técnicas al material original

Archivo Afirmación o comportamiento del curso Observación Tratamiento
552 resample('M', on='DATE'); alias 'Y' y 'T' En pandas 3 falla (ValueError, verificado); los alias actuales son 'ME', 'YE' y 'min' Nota técnica de la sección 3
552 "Hay 2 valores faltantes" Son 2 celdas en una fila (2020-08-04) (verificado) Nota técnica de la sección 2
556 "Muchos picos son a fin de año, en diciembre" En 12 de 16 años el pico es enero (verificado) Nota técnica de la sección 7
558 '-.' como línea "punteada" Es raya y punto; la punteada es ':' Nota técnica de la sección 6
555 Graficar df_btc_monthly.index con df_btc_search.BTC_NEWS_SEARCH Funciona porque coinciden los 73 meses (verificado); es frágil si cambian los datos Sección 6
550 "Telsa" Errata: Tesla —
553, 555 Límites fijos (600 y 15 000) Adecuados para estos datos (máximos verificados: 498,32 y ≈14 156) Secciones 4 y 6
556, 557 Búsquedas como indicador adelantado Coherente con los datos (pico de búsqueda feb. 2009, desempleo oct. 2009); se agrega la distinción entre correlación y causalidad Secciones 7 y 9

16. 📋 Matriz de trazabilidad

Contenido original Archivo de origen Concepto desarrollado Ejercicio original Reto adicional Proyecto relacionado
Google Trends, Bitcoin, Tesla, desempleo, qué se aprende, cuaderno y 5 CSV 550 Sección 0 Preparar el cuaderno — Sección 10
Reto de exploración, formas, máximos y mínimos, describe(), periodicidad, significado de 0–100, parámetros de búsqueda 551 Sección 1 Reto de exploración Escala relativa Secciones 10 y 11
Faltantes con isna().values.any() y .sum(), ubicarlos, dropna(), to_datetime en los 4 DataFrames, resample('M') con last() y mean(), 73 filas 552 Secciones 2 y 3 Retos de limpieza, fechas y remuestreo 'ME'; retos 1–3 de la sección 3 Secciones 10, 11 y 12
Tesla con dos ejes, colores con nombre y hexadecimales, tamaño, fuentes, rotación, título, grosor, DPI, límites, plt.show(), advertencia del convertidor 553 Sección 4 Retos de estilo plt contra ax, savefig Secciones 10 y 12
matplotlib.dates, YearLocator, MonthLocator, DateFormatter, Model 3 en 2016 554 Sección 5 Localizadores Códigos de formato Secciones 10, 11 y 12
Bitcoin: título, límites, linestyle='--', marker='o', índice de la serie mensual, 2018 y 2019 555 Sección 6 Reto de Bitcoin Tabla de estilos; fechas propias Sección 10
Desempleo, FRED, cuadrícula, estacionalidad, crisis de 2008, pico de 2013, media móvil, indicador adelantado 556 Sección 7 Retos de cuadrícula y media móvil Estacionalidad comprobada; retos 1–3 Secciones 10, 11 y 12
Datos con 2020, COVID 557 Sección 8 Reto de 2020 Reescalado de Google Trends Sección 10
Resumen del día, cuaderno completo 558 Sección 8 — — Sección 10
(No existe en el curso original) — Sección 9 — Correlación y causalidad Secciones 10 y 12
(No existe en el curso original) — — — ¿Qué busca Colombia? Sección 11
(No existe en el curso original) — — — Observatorio de Datos del Colegio Sección 12

17. 📦 Evidencias de aprendizaje del Día 75

  • El cuaderno de las tres historias con Google Trends y sus 4 gráficos en PNG.
  • La comprobación numérica de la estacionalidad del desempleo (Reto 1 de la sección 7) y del "adelanto" (Reto 2).
  • El análisis de búsquedas en Colombia (proyecto extra).
  • El Observatorio de Datos del Colegio con todos sus entregables.
  • Cuaderno de errores: resample('M') en pandas 3, contar celdas en vez de filas con NaN, graficar series de distinto tamaño, ax.ylabel en lugar de ax.set_ylabel, marker='circle', series corridas por el orden, comparar valores de Google Trends de descargas distintas, confundir correlación con causalidad.