Saltar al contenido
Inicio 100 Días de Código en Python — Día 25: Datos CSV y la Librería Pandas

100 Días de Código en Python — Día 25: Datos CSV y la Librería Pandas

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 25 (nivel intermedio).

Este tutorial adapta pedagógicamente el Día 25. Las secciones 📝 Ejercicio original del curso provienen de los archivos del curso. Los retos 🟢🟡🟠🔴, el proyecto extra y el proyecto integrador son creaciones de esta adaptación. Las correcciones al material original aparecen como 🛠️ Nota técnica.

Nota sobre las verificaciones: los ejemplos se ejecutaron con Python 3.14 y pandas 3.0.6. Como el archivo weather_data.csv del curso no está en la carpeta, se usó una reconstrucción con los valores que se mencionan en las lecciones (lunes 12 °C y soleado; máximo 24 °C el domingo; promedio 17,4). Los resultados que aparecen aquí son los obtenidos con esa reconstrucción. El censo de ardillas y el juego de los estados necesitan archivos externos que no están en la carpeta; esas partes se revisaron siguiendo la lógica del código.


Tabla de contenidos

  1. Antes de empezar
  2. Leer datos CSV: de readlines a csv y a pandas
  3. DataFrames y Series: trabajar con columnas y filas
  4. El Gran Censo de Ardillas
  5. 🚀 Proyecto del día: el Juego de los Estados de EE. UU.
  6. 🌟 Proyecto extra: el Juego de los Departamentos de Colombia
  7. 🏆 Proyecto integrador de los Días 24 y 25: el Observatorio de Datos del Colegio
  8. 🧩 Comprueba lo aprendido
  9. 🤖 Programar con apoyo de IA
  10. 🛠️ Correcciones técnicas al material original
  11. 📋 Matriz de trazabilidad
  12. 📦 Evidencias de aprendizaje del Día 25

0. Antes de empezar

(Fuente: 189 - Day 25 Goals- what we will make by the end of the day.md)

Ayer trabajamos con archivos de texto. Hoy trabajaremos con archivos de datos en formato CSV y los analizaremos con pandas, una de las librerías de análisis de datos más populares de Python.

Al final construiremos un juego educativo, inspirado en un cuestionario del sitio Sporcle: un mapa de EE. UU. sin nombres en el que el jugador escribe los estados que recuerda y cada acierto aparece en el mapa.

💡 Idea para la clase: en la sección 5 adaptaremos el juego a los departamentos de Colombia.

Prerequisito general: archivos y rutas (Día 24), listas y append (Día 4), diccionarios (Día 9), textinput, goto y write de Turtle (Días 19 a 21), bucles while con break (Día 5) y el operador in.


1. Leer datos CSV: de readlines a csv y a pandas

(Fuente: 190 - Reading CSV Data in Python.md)

🎯 Objetivo de aprendizaje

  • Reconocer el formato CSV.
  • Comparar tres formas de leerlo y explicar por qué pandas simplifica el trabajo.

📖 Explicación conceptual

Anécdota del curso: en el colegio, a Angela le pidieron anotar durante una semana la temperatura y el clima del noticiero. Ella esperó hasta el último día y buscó los datos en internet. "Si te gusta tomar atajos y te niegas a hacer un trabajo que puede hacer una computadora, estás en el lugar correcto."

¿Qué es un CSV? Comma-Separated Values: valores separados por comas. Es la forma más común de guardar datos tabulares (en forma de tabla, como una hoja de cálculo). Cada línea es una fila, y los valores se separan con comas, sin espacios:

Texto
day,temp,condition
Monday,12,Sunny
Tuesday,14,Rain
...

Se puede descargar cualquier hoja de Google Sheets o de Excel como CSV (Archivo → Descargar → Valores separados por comas).

📝 Ejercicio original del curso 1: leer con readlines

Enunciado: abrir weather_data.csv y guardar cada línea en una lista data.

Python
with open("weather_data.csv") as data_file:
    data = data_file.readlines()
print(data)     # ['day,temp,condition\n', 'Monday,12,Sunny\n', ...]  (verificado)

Funciona, pero cada fila es un solo string con comas y \n. Sacar una columna exigiría mucha "limpieza".

📝 Ejercicio original del curso 2: la librería csv y la lista de temperaturas

csv viene incluida en Python:

Python
import csv

with open("weather_data.csv") as data_file:
    data = csv.reader(data_file)
    temperatures = []
    for row in data:                  # cada row es una lista: ['Monday', '12', 'Sunny']
        if row[1] != "temp":          # salta la fila de encabezados
            temperatures.append(int(row[1]))
    print(temperatures)               # [12, 14, 15, 14, 21, 22, 24]  (verificado)

Reto del curso: que las temperaturas sean números enteros, no strings. Por eso se usa int(row[1]).

Observación del curso: funciona, pero son 8 líneas para sacar una columna. Con datos grandes, esto se vuelve doloroso.

📖 La tercera forma: pandas

pandas no viene incluida: hay que instalarla en el proyecto (en PyCharm, sobre la línea roja de import pandas → Install package pandas; en la terminal, pip install pandas).

Python
import pandas

data = pandas.read_csv("weather_data.csv")
print(data)            # una tabla con encabezados y un índice numerado
print(data["temp"])    # toda la columna temp
  • read_csv solo exige la ruta del archivo; todo lo demás es opcional.
  • pandas toma la primera fila como nombres de las columnas.
  • Tres líneas en lugar de ocho, y un formato más claro.

Consejo del curso: al usar una librería nueva, lee su guía de introducción (Getting started en pandas.pydata.org (se abre en otra pestaña)). Responde preguntas como "¿qué tipo de datos maneja?" o "¿cómo leo y escribo tablas?".

Retos adicionales (creados para esta adaptación)

  • 🟢 Reto 1 — Aplicación: crea mi_semana.csv con la temperatura y el clima de tu municipio durante 7 días (búscalos en una fuente confiable y cítala). Léelo con las tres formas.
  • 🟡 Reto 2 — Ampliación: con la librería csv, obtén la lista de días lluviosos.
  • 🟠 Reto 3 — Desafío: investiga csv.DictReader. ¿En qué se diferencia de csv.reader? Reescribe el ejercicio de las temperaturas con él.
  • 🔴 Reto 4 — Pensamiento computacional: ¿qué pasa con csv.reader y con readlines + split(",") si una celda contiene una coma, como "Soleado, con viento"? Pruébalo y explica cuál de las dos formas lo maneja bien.

2. DataFrames y Series: trabajar con columnas y filas

(Fuente: 191 - DataFrames & Series- Working with Rows & Columns.md)

🎯 Objetivo de aprendizaje

  • Diferenciar un DataFrame de una Series.
  • Seleccionar columnas, filtrar filas y calcular estadísticas.
  • Crear un DataFrame y guardarlo como CSV.

📖 Explicación conceptual

Consejo del curso: con una librería nueva, usa type() para saber con qué estás trabajando.

Estructura Equivale a… Ejemplo
DataFrame Una tabla completa (una hoja de Excel o de Google Sheets) data
Series Una columna, parecida a una lista data["temp"]

(Verificado: type(data) → DataFrame y type(data["temp"]) → Series.)

"Una vez entiendes que la tabla es un DataFrame y cada columna es una Series, llevas la mitad del camino."

Conversiones (sección Serialization / IO / conversion de la referencia de la API (se abre en otra pestaña)):

Python
data_dict = data.to_dict()          # {'day': {0: 'Monday', ...}, 'temp': {0: 12, 1: 14, ...}, ...}
temp_list = data["temp"].to_list()  # [12, 14, 15, 14, 21, 22, 24]

📝 Ejercicio original del curso 1: temperatura promedio

Dos soluciones válidas que dan el mismo resultado (verificado: 17,43, que el curso redondea a 17,4):

Python
# Opción A: Python "puro"
average = sum(temp_list) / len(temp_list)

# Opción B: el método de pandas
average = data["temp"].mean()

La opción B es más corta. Las Series también tienen median(), mode() y muchos más métodos estadísticos.

📝 Ejercicio original del curso 2: temperatura máxima

Python
print(data["temp"].max())    # 24

Dos formas de seleccionar una columna

Python
data["condition"]    # como un diccionario (sirve con cualquier nombre de columna)
data.condition       # como un atributo (más corto)

Ambas funcionan igual. Distinguen mayúsculas: si la columna se llama Condition, debes escribirla así. La forma con corchetes es la única que sirve si el nombre tiene espacios (lo veremos con las ardillas).

Filtrar filas

Python
data[data.day == "Monday"]              # la fila del lunes
data[data.temp == data.temp.max()]      # la fila con la temperatura máxima

Resultado verificado de la segunda línea:

Texto
      day  temp condition
6  Sunday    24     Sunny

Cómo leerlo: data.day == "Monday" produce una Series de True y False, una por fila. Al ponerla dentro de data[...], pandas devuelve solo las filas con True.

Regla del curso: dentro de los corchetes, un nombre de columna devuelve una columna; una condición devuelve filas.

📝 Ejercicio original del curso 3: la temperatura del lunes en Fahrenheit

Python
monday = data[data.day == "Monday"]
monday_temp = monday.temp[0]
monday_temp_F = monday_temp * 9 / 5 + 32
print(monday_temp_F)       # 53.6  (verificado; coincide con el conversor que usa el curso)

🛠️ Nota técnica (verificada): monday.temp[0] funciona solo porque el lunes está en la fila 0. El [0] busca la etiqueta 0 del índice, no "el primer elemento". Con el martes (fila 1), tuesday.temp[0] produce KeyError: 0. Las formas seguras son tuesday.temp.iloc[0] (el primero por posición) o tuesday.temp.item() (el único valor), que el curso usa más adelante. Ambas devuelven 14.

Crear un DataFrame y guardarlo

Python
data_dict = {
    "students": ["Amy", "James", "Angela"],
    "scores": [76, 56, 65],
}
data = pandas.DataFrame(data_dict)
data.to_csv("new_data.csv")

Contenido verificado de new_data.csv:

Texto
,students,scores
0,Amy,76
1,James,56
2,Angela,65

🛠️ Nota técnica (verificada): observa la primera columna sin nombre con 0, 1, 2: es el índice de pandas. Si no la quieres en el archivo, usa data.to_csv("new_data.csv", index=False).

Hacia dónde vamos: el curso anuncia que más adelante usaremos pandas junto con NumPy y Matplotlib para analizar grandes volúmenes de datos.

⚠️ Errores frecuentes

Error Qué ocurre Solución
data["Temp"] si la columna es temp KeyError: 'Temp' Copia el nombre exacto del encabezado
data.primary fur color SyntaxError Nombres con espacios: data["Primary Fur Color"]
fila.temp[0] en una fila que no es la primera KeyError: 0 .iloc[0] o .item()
Olvidar instalar pandas ModuleNotFoundError: No module named 'pandas' Instálala en el entorno del proyecto (Día 18)

Retos adicionales (creados para esta adaptación)

  • 🟢 Reto 1: con tu mi_semana.csv, calcula el promedio, la mínima y la mediana.
  • 🟡 Reto 2: muestra solo los días con temperatura mayor que el promedio.
  • 🟠 Reto 3: agrega al DataFrame una columna nueva temp_F con la conversión a Fahrenheit en una sola línea (pista: una Series se puede multiplicar completa). Guarda el resultado con index=False.
  • 🔴 Reto 4: investiga value_counts() y úsalo para contar cuántos días hubo de cada condición. Compáralo con lo que harías con un diccionario y un for.

3. El Gran Censo de Ardillas

(Fuente: 192 - The Great Squirrel Census Data Analysis (with Pandas!).md)

Contexto

En 2018, un grupo de voluntarios recorrió todo Central Park (Nueva York) y registró cada ardilla que encontró: ubicación, identificación, edad (adulta o juvenil) y color principal del pelaje (gris, canela o negro). Los datos son abiertos y se pueden descargar como CSV en el portal de datos abiertos de la ciudad de Nueva York, que el curso enlaza en sus recursos.

💡 Para discutir: un trabajo de campo enorme y tedioso, hecho por voluntarios, permite que cualquiera analice los datos en segundos. ¿Qué datos abiertos existen en Colombia? Explora datos.gov.co (se abre en otra pestaña).

📝 Ejercicio original del curso

Enunciado: a partir del censo, crear squirrel_count.csv con una tabla pequeña: cada color de pelaje y cuántas ardillas hay de ese color, según la columna Primary Fur Color.

🔍 Antes de programar

  • ¿Qué columna necesitas? ¿Por qué hay que usar corchetes para seleccionarla?
  • ¿Cómo obtienes solo las filas de ardillas grises?
  • ¿Cómo cuentas esas filas?
  • ¿Qué estructura de Python usarás para construir el nuevo DataFrame?

Solución del curso (en palabras):

  1. data = pandas.read_csv("2018_Central_Park_Squirrel_Census_-_Squirrel_Data.csv"). PyCharm autocompleta el nombre largo; el curso sugiere renombrar el archivo si lo prefieres.
  2. Filtrar por color: data[data["Primary Fur Color"] == "Gray"]. Ojo con la ortografía: el dato está en inglés estadounidense, Gray, no Grey.
  3. Contar con len(...). El curso obtuvo 2473 ardillas grises; también cuenta las de color Cinnamon (canela) y Black.
  4. Construir un diccionario: {"Fur Color": ["grey", "red", "black"], "Count": [grey_count, red_count, black_count]}.
  5. pandas.DataFrame(data_dict).to_csv("squirrel_count.csv").

Conclusión del curso: hay principalmente ardillas grises, algunas canela y muy pocas negras.

Alternativa de esta adaptación: data["Primary Fur Color"].value_counts() cuenta todos los colores en una línea. La solución del curso es más larga, pero obliga a practicar el filtrado de filas, y ese es su objetivo pedagógico. Las dos son válidas.

Pregunta de análisis: en el censo hay ardillas cuyo color no se registró (celdas vacías). ¿La suma de las tres cuentas coincide con el total de filas? ¿Qué harías con esos datos faltantes al presentar resultados?

Retos adicionales (creados para esta adaptación)

  • 🟢 Reto 1: guarda squirrel_count.csv sin la columna de índice.
  • 🟡 Reto 2: agrega una columna con el porcentaje de cada color.
  • 🟠 Reto 3: cuenta cuántas ardillas son adultas y cuántas juveniles para cada color. (Investiga filtrar con dos condiciones: (cond1) & (cond2).)
  • 🔴 Reto 4: descarga un conjunto de datos de datos.gov.co (se abre en otra pestaña) que te interese y responde tres preguntas con pandas. Cita la fuente.

4. 🚀 Proyecto del día: el Juego de los Estados de EE. UU.

(Fuentes: 193 - U.S. States Game Part 1- Setup.md, 194 - U.S. States Game Part 2- Challenge with .csv.md, 195 - U.S. States Game Part 3- Saving Data to .csv.md)

Problema

Crear un juego en el que el jugador escribe nombres de estados de EE. UU. y cada acierto aparece escrito en su lugar del mapa.

Contexto

Es una herramienta educativa: el curso invita a usarla con estudiantes y a adaptarla a otros países, al mundo o a cualquier lista (plantas, animales…).

Archivos del proyecto inicial (según la lección 193)

Archivo Contenido
50_states.csv Columnas state, x, y: el nombre de cada estado y las coordenadas donde escribirlo
blank_states_img.gif El mapa sin nombres
main.py Vacío

Requisitos funcionales

  1. El mapa como fondo de la ventana.
  2. Un cuadro de texto pide un estado; el título muestra el progreso: "3/50 States Correct".
  3. Se acepta la respuesta sin importar las mayúsculas ("ohio", "OHIO" y "Ohio").
  4. Si es correcto, el nombre se escribe en las coordenadas del estado. Si no, se vuelve a preguntar.
  5. Al escribir exit, el juego termina y genera states_to_learn.csv con los estados que faltaron.

Construcción paso a paso

Versión 1 — Una imagen como forma de la tortuga. Truco nuevo: se registra la imagen como una "forma" y se le asigna a una tortuga.

Python
import turtle

screen = turtle.Screen()
screen.title("U.S. States Game")
image = "blank_states_img.gif"
screen.addshape(image)
turtle.shape(image)
  • Error típico que muestra el curso: couldn't open "blank_state_img.gif": no such file or directory, porque faltaba una s en el nombre. Revisa la ortografía de las rutas (Día 24).

🛠️ Nota técnica (verificada en la documentación del módulo): el curso dice que Turtle solo acepta imágenes GIF. Eso era cierto en versiones anteriores. En la versión de Python usada para esta verificación (3.14), la documentación de register_shape/addshape ya acepta PNG, GIF, PGM y PPM. Si usas una versión antigua, convierte la imagen a GIF.

Versión 2 — ¿De dónde salen las coordenadas? El curso encontró en Stack Overflow un código para saber las coordenadas de un clic:

Python
def get_mouse_click_coor(x, y):
    print(x, y)

turtle.onscreenclick(get_mouse_click_coor)   # función de orden superior (Día 19)
turtle.mainloop()                            # mantiene la ventana abierta, alternativa a exitonclick

Haciendo clic sobre cada estado se obtienen sus coordenadas. El curso ya hizo ese trabajo "realmente tedioso" y lo guardó en 50_states.csv. Este código te servirá en la sección 5.

¿Por qué mainloop() y no exitonclick()? Porque si la ventana se cierra al primer clic, no puedes hacer clic en los estados.

Versión 3 — Comprobar la respuesta (desafío del curso: dedícale al menos 20 minutos antes de ver la solución).

"Hay que sentir la lucha para aprender. Si la respuesta no viene de ti, no vas a progresar."

Python
data = pandas.read_csv("50_states.csv")
all_states = data.state.to_list()

answer_state = screen.textinput(title="Guess the State", prompt="What's another state's name?").title()

if answer_state in all_states:
    t = turtle.Turtle()
    t.hideturtle()
    t.penup()
    state_data = data[data.state == answer_state]
    t.goto(state_data.x.item(), state_data.y.item())
    t.write(answer_state)

El error que el curso encuentra y cómo lo investiga. Primero escribió t.goto(state_data.x, state_data.y) y apareció un error de Tk (bad screen distance). El curso copió el mensaje, lo buscó en Google y descubrió que era un problema de tipos: state_data.x no es un número, sino una Series (índice + valor, algo como 34 175). La solución fue .item(), que extrae el único valor.

¿Por qué convertir a lista antes de usar in? El curso lo indica sin explicar la razón. Verificación de esta adaptación:

Python
"Monday" in data.day             # False  ← ¡aunque Monday sí está!
0 in data.day                    # True   ← revisa las ETIQUETAS del índice, no los valores
"Monday" in data.day.to_list()   # True   ✅

Con una Series, in busca en el índice. Por eso hay que convertirla a lista (o usar .values).

.title(): convierte a "Mayúscula Inicial" en cada palabra ("new york".title() → "New York"), para aceptar cualquier combinación de mayúsculas.

Versión 4 — Repetir hasta adivinar los 50:

Python
guessed_states = []
while len(guessed_states) < 50:
    answer_state = screen.textinput(title=f"{len(guessed_states)}/50 States Correct",
                                    prompt="What's another state's name?").title()
    if answer_state in all_states:
        guessed_states.append(answer_state)
        # ... escribir el estado en el mapa ...

Versión final — Salir y generar la lista de estudio:

Python
    if answer_state == "Exit":       # "Exit" con E mayúscula, porque ya se aplicó .title()
        missing_states = []
        for state in all_states:
            if state not in guessed_states:
                missing_states.append(state)
        new_data = pandas.DataFrame(missing_states)
        new_data.to_csv("states_to_learn.csv")
        break

En la prueba del curso, después de acertar los 4 estados que empiezan por A (hay exactamente 4), se generó un archivo con los 46 estados que faltaban. (En la transcripción aparece "44", pero 50 − 4 = 46.)

Nota para el Día 26: el bucle que construye missing_states se puede escribir en una línea con una comprensión de listas, el tema del día siguiente.

Pruebas

Caso Resultado esperado
Escribir ohio "Ohio" aparece en su lugar; el título pasa a 1/50
Escribir Narnia No pasa nada; se vuelve a preguntar
Escribir exit Se cierra y se crea states_to_learn.csv
Escribir dos veces Ohio ⚠️ ¿Qué pasa con el contador? (ver 🧪)
Pulsar Cancelar ⚠️ ¿Qué error aparece? (ver 🧪)

🧪 Prueba y depuración

El código del curso tiene tres problemas que no se mencionan en las lecciones. Analízalos y corrígelos:

  1. Estados repetidos. Si escribes "Ohio" dos veces, se agrega dos veces a guessed_states: el contador sube a 2/50 y el nombre se escribe encima de sí mismo. Si alguien repite un estado 50 veces, el juego termina "ganado" con un solo estado. (Pista: and answer_state not in guessed_states.)
  2. El botón Cancelar. textinput devuelve None si se cancela, y None.title() produce AttributeError: 'NoneType' object has no attribute 'title' (verificado). (Pista: guarda primero la respuesta, revisa si es None y solo después aplica .title().)
  3. El índice en el CSV de salida. states_to_learn.csv sale con una columna de índice (0, 1, 2…) y un encabezado 0 poco claro. (Pista: pandas.DataFrame(missing_states, columns=["state"]) y index=False.)

⭐ Extensión del proyecto

  • Mostrar al final, en pantalla, cuántos estados acertaste y en cuánto tiempo (time.time()).
  • Escribir los estados que faltaron en rojo sobre el mapa al salir, para estudiarlos visualmente.
  • Guardar el récord de cada jugador en un CSV (combinando los Días 24 y 25).

5. 🌟 Proyecto extra: el Juego de los Departamentos de Colombia

Situación

El área de Ciencias Sociales quiere un juego para repasar los 32 departamentos de Colombia y sus capitales.

Requisitos

  1. Construye tus propios datos. Consigue un mapa de Colombia con la división política y sin nombres (de una fuente con licencia libre, citándola). Con el código de onscreenclick de la sección 4, registra las coordenadas de cada departamento y crea departamentos.csv con las columnas departamento, capital, x, y.
  2. Modo 1 — Departamentos: como el juego del curso.
  3. Modo 2 — Capitales: el mapa muestra un departamento resaltado (un dot en sus coordenadas) y el jugador escribe su capital.
  4. Al salir, genera para_estudiar.csv con lo que faltó, sin columna de índice.
  5. Corrige los tres problemas de la sección 🧪.

⚠️ Dos trampas del español (verificadas)

  • .title() no sirve para todos los nombres: "norte de santander".title() da "Norte De Santander", con De mayúscula, que no coincide con "Norte de Santander". Lo mismo pasa con "Valle del Cauca" o "San Andrés y Providencia". Decisión que debes tomar: ¿comparas todo en minúsculas (.lower() en la respuesta y en la lista) y escribes en el mapa el nombre tal como está en el CSV?
  • Las tildes: ¿"Bogota" debe contar como "Bogotá"? ¿Y "atlantico" como "Atlántico"? Decide una regla y justifícala. (Investiga unicodedata.normalize si quieres aceptar respuestas sin tilde.) Y recuerda leer el CSV con la codificación correcta (Día 24): pandas.read_csv("departamentos.csv", encoding="utf-8").

Reflexión

¿Cuánto tiempo te tomó registrar las 32 coordenadas? ¿Qué te dice eso sobre el valor de los datos abiertos como el censo de ardillas?


6. 🏆 Proyecto integrador de los Días 24 y 25: el Observatorio de Datos del Colegio

Proyecto integrador creado para esta adaptación. Integra archivos y rutas (Día 24), CSV y pandas (Día 25), funciones, diccionarios, validación y comunicación de resultados.

Situación problema

El consejo estudiantil hizo una encuesta sobre cómo llegan los estudiantes al colegio y cuánto tardan. Tiene las respuestas en una hoja de cálculo y necesita conclusiones para proponer mejoras (por ejemplo, una ruta de bicicletas o una campaña de transporte compartido).

Pregunta orientadora

¿Cómo convertir datos crudos en información útil para tomar decisiones en la comunidad educativa?

Requerimientos

  1. Datos: crea (o solicita al consejo estudiantil, anonimizada) una encuesta en CSV con al menos 40 filas y las columnas: grado, medio (a pie, bicicleta, bus, moto, carro, otro), minutos, barrio_o_vereda y se_siente_seguro (si/no). Incluye a propósito algunas filas con errores: minutos vacíos o negativos, un medio mal escrito.
  2. Limpieza: un programa limpiar.py que lea datos/encuesta.csv, separe las filas válidas de las inválidas y guarde datos/encuesta_limpia.csv y datos/descartadas.csv (con el motivo del descarte).
  3. Análisis: un programa analizar.py que, con pandas, responda:
    • ¿Cuántos estudiantes usan cada medio? (con porcentaje)
    • ¿Cuál es el tiempo promedio y el máximo por medio?
    • ¿Qué grado tarda más en promedio?
    • ¿Qué porcentaje no se siente seguro, por medio de transporte?
  4. Salida: guardar cada respuesta como un CSV en resultados/ (sin columna de índice) y un resultados/conclusiones.txt escrito por el programa con las cifras principales.
  5. Rutas con Path(__file__).parent, encoding="utf-8" y funciones con docstring.

Etapas de desarrollo

  1. Diseño de la encuesta y de las preguntas de análisis.
  2. Limpieza de los datos.
  3. Análisis con pandas.
  4. Redacción de las conclusiones y una propuesta para el colegio basada en los datos.

Entregables

  • Código, datos (anonimizados) y resultados.
  • Una presentación corta para el consejo estudiantil: 3 hallazgos y 1 propuesta.
  • Una reflexión: ¿qué limitaciones tienen tus datos? (tamaño de la muestra, sinceridad de las respuestas, filas descartadas…)

Casos de prueba

Caso Esperado
Fila con minutos vacío Va a descartadas.csv con el motivo
Medio escrito como "Bus " o "BUS" Se normaliza a "bus"
Ejecutar analizar.py antes de limpiar.py Mensaje claro indicando que falta el archivo limpio
Los CSV de resultados Sin columna de índice sin nombre

Criterios técnicos

  • Ningún dato personal identificable (nombres, documentos) en ningún archivo.
  • Los resultados se pueden volver a generar ejecutando los dos programas.
  • Cada cifra de las conclusiones se puede rastrear hasta un CSV de resultados.

7. 🧩 Comprueba lo aprendido

Conceptuales

  1. ¿Qué es un CSV? ¿Por qué es tan usado?
  2. ¿Qué diferencia hay entre un DataFrame y una Series?
  3. ¿Por qué "Monday" in data.day da False?

Análisis de código

Python
data = pandas.read_csv("weather_data.csv")
calidos = data[data.temp > 20]
print(len(calidos), calidos.day.to_list())

Con los datos de este tutorial, ¿qué imprime?

Predicción

¿Qué devuelve data[data.condition == "Rain"].temp.mean() con los datos del tutorial?

Depuración

Python
data = pandas.read_csv("50_states.csv")
answer = screen.textinput("Estado", "Escribe un estado").title()
if answer in data.state:
    row = data[data.state == answer]
    t.goto(row.x, row.y)

Encuentra tres problemas.

Modificación

Cambia el juego de los estados para que, al escribir hint, muestre en el título la primera letra de un estado que aún no has adivinado.

Creación

Con el diccionario {"materia": [...], "nota": [...]} de tus calificaciones, crea un DataFrame, calcula tu promedio y guarda en materias_a_reforzar.csv las materias con nota menor que tu promedio.


8. 🤖 Programar con apoyo de IA

El curso modela una práctica excelente: ante un error extraño (bad screen distance), copió el mensaje y lo investigó hasta entender la causa (un problema de tipos). Hoy aplicaremos lo mismo con IA.

Actividad: investigar un error con IA y con la documentación.

  1. Provoca el error: escribe t.goto(state_data.x, state_data.y) sin .item().
  2. Pega el mensaje de error en una IA y pregunta por qué ocurre, no solo cómo arreglarlo.
  3. Verifica su explicación: imprime type(state_data.x) y state_data.x. ¿Coincide con lo que dijo?
  4. Pregúntale: "¿in sobre una Series de pandas revisa los valores o el índice?". Compruébalo tú con el ejemplo de la sección 4 y con la documentación de pandas (se abre en otra pestaña).
  5. Anota en tu cuaderno si la IA acertó, qué verificaste y con qué fuente.

9. 🛠️ Correcciones técnicas al material original

Archivo Afirmación o comportamiento del curso Observación Tratamiento
191 monday.temp[0] para obtener el valor Funciona solo si la fila tiene la etiqueta 0; con el martes da KeyError: 0. Usar .iloc[0] o .item() (verificado con pandas 3.0.6) Nota técnica del Tema 2
191, 192, 195 to_csv("archivo.csv") Agrega una columna de índice sin nombre; index=False la evita (verificado) Nota técnica del Tema 2 y 🧪 del proyecto
193 Turtle solo funciona con imágenes GIF En la versión usada (Python 3.14), la documentación del módulo acepta PNG, GIF, PGM y PPM Nota técnica del proyecto
194 Convertir a lista antes de usar in Correcto, y la razón es que in sobre una Series revisa el índice (verificado) Versión 3 del proyecto
194 answer_state se agrega a guessed_states sin revisar Los estados repetidos inflan el contador y pueden terminar el juego 🧪 del proyecto
194 screen.textinput(...).title() Al pulsar Cancelar, AttributeError con None (verificado) 🧪 del proyecto
195 Faltaban "44 estados" tras acertar 4 50 − 4 = 46; probablemente un error de transcripción Versión final del proyecto
(adaptación) .title() normaliza las respuestas No sirve para nombres en español con preposiciones: "Norte De Santander" (verificado) Sección 5

10. 📋 Matriz de trazabilidad

Contenido original Archivo de origen Concepto desarrollado Ejercicio original Reto adicional Proyecto relacionado
Objetivos: CSV, pandas, juego de los estados 189 Sección 0 — — Sección 4
CSV, readlines, csv.reader, read_csv 190 Tema 1 Lista data y lista de temperaturas Retos 1–4 del Tema 1 Secciones 3, 4 y 6
DataFrame, Series, to_dict, to_list, mean, max, filtros, Fahrenheit, DataFrame(...), to_csv 191 Tema 2 Promedio, máximo, fila máxima, lunes en °F Retos 1–4 del Tema 2 Secciones 3, 4, 5 y 6
Censo de ardillas 192 Tema 3 squirrel_count.csv Retos 1–4 del Tema 3 (datos.gov.co) Sección 6
Imagen como forma, onscreenclick, mainloop, textinput 193 Sección 4, versiones 1 y 2 Configurar el juego Registro de coordenadas Sección 5
Comprobar respuestas, .item(), .title(), while 194 Sección 4, versiones 3 y 4 Reto de los estados Depuración (repetidos, Cancelar) Sección 5
exit, estados faltantes, states_to_learn.csv 195 Sección 4, versión final Guardar los faltantes Depuración (índice en el CSV) Secciones 5 y 6
(No existe en el curso original) — — — Departamentos de Colombia Sección 5
(No existe en el curso original) — — — Observatorio de Datos del Colegio Sección 6

11. 📦 Evidencias de aprendizaje del Día 25

  • mi_semana.csv leído de las tres formas, con la comparación escrita.
  • Las respuestas de los ejercicios de DataFrames: promedio, máximo, fila máxima y conversión a Fahrenheit.
  • squirrel_count.csv (y, si lo hiciste, el análisis de un conjunto de datos de datos.gov.co).
  • Juego de los estados con los tres problemas corregidos y captura de una partida.
  • Proyecto extra (Departamentos de Colombia) o integrador (Observatorio de Datos).
  • Cuaderno de errores: ModuleNotFoundError de pandas, KeyError por nombres de columna, KeyError: 0 con temp[0], bad screen distance por pasar una Series a goto, in sobre una Series, AttributeError con None.title(), la columna de índice en los CSV y la imagen que no se encuentra por un error de ortografía.