# visualizacion-geospacial-avanzada-con-geopandas
Visualización Geospacial Avanzada con GeoPandas
Volver a la portada del cursoUso de Matplotlib con GeoPandas
Sección 4 · Integración con Pandas y Matplotlib
Uso de Matplotlib con GeoPandas
GeoDataFrame.plot() dibuja con Matplotlib, así que todo lo que sabes de Matplotlib sirve para tus mapas: ejes, títulos, anotaciones, subgráficos y estilos. La diferencia es que cada capa del mapa es una llamada a plot() sobre los mismos ejes. Esta lección construye mapas temáticos completos con los estados y las ciudades de México.
Preparar los datos
Cargamos los estados y las ciudades de Natural Earth, limpiamos la capa de estados y proyectamos todo a EPSG:6372, un CRS en metros pensado para México:
import geopandas as gpd
import matplotlib.pyplot as plt
NE = "https://naciscdn.org/naturalearth/10m/cultural/"
estados = gpd.read_file(NE + "ne_10m_admin_1_states_provinces.zip",
where="iso_a2 = 'MX'", columns=["name", "iso_a2"])
estados = estados.dropna(subset=["name"]).to_crs(6372)
estados["name"] = estados["name"].replace({"Distrito Federal": "Ciudad de México"})
ciudades = gpd.read_file(NE + "ne_10m_populated_places_simple.zip",
where="iso_a2 = 'MX'",
columns=["name", "pop_max", "iso_a2"]).to_crs(6372)
ciudades["name"] = ciudades["name"].replace({"Mexico City": "Ciudad de México"})
print(len(estados), "estados,", len(ciudades), "ciudades")
Natural Earth escribe algunos nombres en inglés, como «Mexico City»; conviene corregirlos antes de usarlos como etiquetas.
Capas sobre los mismos ejes
La regla es crear los ejes una vez y pasar ax=ax a cada capa. El orden de las llamadas es el orden de apilado: primero el fondo, al final los puntos y los textos.
fig, ax = plt.subplots(figsize=(10, 7))
estados.plot(ax=ax, color="#eeeeee", edgecolor="gray", linewidth=0.4)
grandes = ciudades.nlargest(10, "pop_max")
grandes.plot(ax=ax, color="crimson", markersize=grandes.pop_max / 4e4,
alpha=0.7, edgecolor="black", linewidth=0.3)
for _, c in grandes.head(3).iterrows():
ax.annotate(c["name"], xy=(c.geometry.x, c.geometry.y),
xytext=(5, 5), textcoords="offset points", fontsize=9)
ax.set_title("Las 10 ciudades más pobladas de México")
ax.set_axis_off()
fig.savefig("ciudades.png", dpi=150, bbox_inches="tight")
markersize acepta una columna, así el tamaño del punto codifica la población. set_axis_off() quita las coordenadas en metros del CRS proyectado, que no aportan nada al lector.
Mapas de coropletas
Una coropleta colorea cada polígono según un valor. Basta con column; con legend=True aparece la barra de color. Una regla importante: colorea tasas o densidades, no totales. Un estado grande acumula más de todo solo por su tamaño, y el color terminaría mostrando el área. Para practicar la mecánica usamos la superficie misma, una propiedad de cada polígono; en el proyecto final colorearás una densidad.
estados["area_km2"] = estados.area / 1e6
ax = estados.plot(column="area_km2", cmap="viridis", legend=True,
edgecolor="white", linewidth=0.3, figsize=(10, 6),
legend_kwds={"label": "Superficie (km²)", "shrink": 0.6})
ax.set_title("Superficie por estado")
ax.set_axis_off()
Esquemas de clasificación
Con una escala continua, un valor extremo puede aplastar al resto. El parámetro scheme (requiere la biblioteca mapclassify) agrupa los valores en k clases y cambia por completo la lectura del mapa:
"Quantiles": el mismo número de estados en cada clase. Muestra el orden, pero puede juntar valores muy distintos."EqualInterval": clases del mismo ancho. Con un valor extremo, casi todo cae en la primera clase."NaturalBreaks"(Jenks): busca cortes donde los datos se separan de forma natural. Usa un algoritmo con inicios aleatorios, así que dos ejecuciones pueden dar clases un poco distintas; si necesitas resultados reproducibles, usa"FisherJenks", que calcula los cortes óptimos de forma exacta.
fig, axes = plt.subplots(1, 3, figsize=(16, 4.5))
for ax, esquema in zip(axes, ["Quantiles", "EqualInterval", "NaturalBreaks"]):
estados.plot(column="area_km2", scheme=esquema, k=5, cmap="YlGnBu",
edgecolor="gray", linewidth=0.3, ax=ax, legend=True,
legend_kwds={"loc": "lower left", "fontsize": 7})
ax.set_title(esquema)
ax.set_axis_off()
fig.savefig("esquemas.png", dpi=120, bbox_inches="tight")
Valores faltantes
Si algún polígono no tiene dato, por omisión no se dibuja y el mapa queda con huecos que parecen errores. missing_kwds los muestra con un estilo propio, por ejemplo gris con rayas y la etiqueta «Sin datos» en la leyenda:
estados.loc[estados["name"] == "Oaxaca", "area_km2"] = None
ax = estados.plot(column="area_km2", cmap="viridis", legend=True,
missing_kwds={"color": "lightgray", "hatch": "///",
"label": "Sin datos"})
ax.set_axis_off()
Trampas comunes
- Coropletas de totales. Normaliza por área o por población antes de colorear.
- Dibujar en grados con la forma equivocada. En
EPSG:4326el mapa de México sale estirado; proyecta para dibujar. - Olvidar
ax=ax. Cada capa termina en su propia figura. - Paletas arcoíris.
jetcrea fronteras visuales falsas; usaviridis,YlGnBuo paletas divergentes si hay un centro con sentido. - Leyendas sin unidades. Escribe siempre qué se mide y en qué unidad.
Cierre
Un buen mapa temático responde una sola pregunta. Elige la variable (mejor una tasa), el esquema de clases que la cuente con honestidad y una paleta legible; después agrega solo el contexto que ayude a leerla.