# introduccion-a-la-ciencia-de-datos-con-python
Introducción a la Ciencia de Datos con Python
Volver a la portada del cursoAnálisis de datos avanzados con pandas
Sección 2 · Manipulación y Análisis de Datos
Análisis de datos avanzados con pandas
Con groupby y mean ya sabes que en 2007 la vida media en Africa era de 54.8 años y en Europe de 77.6. Este notebook da el siguiente paso: resumir varias métricas a la vez, poner la evolución en una tabla continente × año, encontrar los países que retrocedieron y limpiar una copia de Gapminder a la que le metemos errores a propósito para practicar. El notebook pandas-gapminder acompaña esta lección; aquí tienes la guía de lo que hace cada sección y qué debe darte.
1. Resúmenes con nombre: agg
agg con tuplas (columna, función) calcula varias métricas por grupo y les pone nombre en un solo paso:
import plotly.express as px
gap = px.data.gapminder().drop(columns=["iso_alpha", "iso_num"])
g07 = gap[gap["year"] == 2007]
resumen = g07.groupby("continent").agg(
paises=("country", "count"),
vida_media=("lifeExp", "mean"),
pib_pc_mediano=("gdpPercap", "median"),
poblacion=("pop", "sum"),
)
print(resumen.round(1))
Asia suma 3812 millones de habitantes en 33 países; Oceania, 2 países. El PIB per cápita mediano de Africa es de 1452 dólares y el de Europe de 28 054. Se usa la mediana porque el PIB está muy sesgado: unos pocos países ricos jalan la media hacia arriba.
2. Tablas continente × año: pivot_table
pivot_table pasa los datos de formato largo a ancho para leer la evolución de un vistazo:
tabla = gap.pivot_table(index="continent", columns="year",
values="lifeExp", aggfunc="mean")
print(tabla[[1952, 1977, 2007]].round(1))
Africa pasa de 39.1 a 49.6 y a 54.8; Asia, de 46.3 a 59.6 y a 70.7. Asia ganó 24 años en el periodo; Africa, casi 16. La tabla ancha es buena para mirar; para seguir calculando conviene volver al formato largo.
3. Columnas nuevas con assign y comparaciones con merge
assign crea columnas sin modificar el original, por ejemplo pib_total = pop * gdpPercap. Para comparar 1952 con 2007 país por país, se separan los dos años y se unen por country:
a = gap.loc[gap["year"] == 1952, ["country", "lifeExp"]]
b = gap.loc[gap["year"] == 2007, ["country", "continent", "lifeExp"]]
ambos = a.merge(b, on="country", suffixes=("_1952", "_2007"))
ambos["ganancia"] = ambos["lifeExp_2007"] - ambos["lifeExp_1952"]
print(ambos.shape, round(ambos["ganancia"].mean(), 2)) # (142, 5) 17.95
print(ambos.nlargest(3, "ganancia")[["country", "ganancia"]].round(1))
La ganancia media es de 17.95 años. Las mayores: Oman 38.1, Vietnam 33.8 e Indonesia 33.2. Solo dos países terminan peor que en 1952: Zimbabwe (−5.0) y Swaziland (−1.8). Después de un merge, revisa siempre el número de filas: si sale más de 142, alguna llave estaba repetida.
4. Cambios dentro de cada país: diff por grupo
Para ver retrocesos entre mediciones consecutivas, se ordena por país y año y se aplica diff dentro de cada país. Sin el groupby, la primera fila de un país se restaría de la última del anterior.
gap = gap.sort_values(["country", "year"])
gap["cambio"] = gap.groupby("country")["lifeExp"].diff()
caidas = gap[gap["cambio"] < -5]
print(len(caidas)) # 15
print(caidas.nsmallest(3, "cambio")[["country", "year", "lifeExp", "cambio"]].round(1))
Hay 15 caídas de más de 5 años. La peor es Rwanda en 1992: −20.4 años, hasta 23.6. El periodo coincide con la guerra civil iniciada en 1990, que desembocó en el genocidio de 1994; la serie cada 5 años suaviza los eventos. Le siguen Zimbabwe 1997 (−13.6), Lesotho 2002 (−11.0), Swaziland 2002 (−10.4) y Botswana 1997 (−10.2), todos en África austral durante la epidemia de VIH/sida. Detrás de cada número atípico hay una historia: investígala antes de tratarlo como error.
5. Limpieza de una copia sucia
Gapminder viene limpio, así que el notebook define gapminder_sucio(semilla=42): la tabla de 2007 con nulos, texto inconsistente y duplicados metidos a propósito. Tiene 145 filas, 5 nulos en lifeExp, 3 en gdpPercap, 3 filas duplicadas y 10 escrituras distintas de continente («africa», «Africa », «AFRICA»…). La limpieza va en este orden:
limpio = sucio.drop_duplicates().copy()
limpio["continent"] = limpio["continent"].str.strip().str.title()
mediana = limpio.groupby("continent")[["lifeExp", "gdpPercap"]].transform("median")
limpio[["lifeExp", "gdpPercap"]] = limpio[["lifeExp", "gdpPercap"]].fillna(mediana)
print(limpio.shape, limpio.isna().sum().sum()) # (142, 6) 0
transform("median") devuelve, para cada fila, la mediana de su continente, con el mismo índice que la tabla; por eso fillna rellena cada nulo con el valor de su grupo. Quedan 142 filas, 5 continentes y 0 nulos.
Imputar inventa datos, y el notebook lo mide: comparado con el valor real, el error en lifeExp es de 7.3 años en Bolivia, 6.1 en Nigeria, 3.1 en Iceland, 0.8 en Venezuela y 0.7 en Slovenia. Si imputas, dilo en el reporte y di cuántas filas afectó.
6. apply y map, con moderación
map con un diccionario sirve para recodificar, por ejemplo continente → código de dos letras. apply con una función de Python recorre fila por fila y es lento; casi siempre existe una versión vectorizada (np.log10, operaciones entre columnas, métodos .str). Úsalo solo cuando no la haya.
Trampas comunes
diffsin agrupar ni ordenar: mezcla países y años.- Imputar con la media global: un país africano recibiría un valor sesgado hacia Europe. Agrupa primero.
- Arreglar el texto después de agrupar: «Africa » y «Africa» quedarían como dos grupos.
- No contar filas después de un
merge: una llave repetida multiplica filas sin avisar.
Cierre
Al terminar el notebook, verifica con números: 142 filas, 0 nulos, 5 continentes y 15 caídas. Si algún conteo no coincide, revisa el orden de los pasos de limpieza antes de seguir.