[Tutorial] Hacer una pirámide de población en R y Python

Con el censo 2020 de México de Inegi

[Tutorial] Hacer una pirámide de población en R y Python

La mejor forma de mostrar la dinámica de una población es con un gráfico de pirámide.

Se le llama así porque por años esa es la forma que ha tomado, cuando ponemos dos gráficos de barras contiguos. Cada barra es la suma de todas las personas en un rango de edades.

En este tutorial:

  • Te daré el código para hacer tus pirámides de población en R y Python.
  • Luego veremos un ejemplo real descargando datos del INEGI
  • Y finamente personalizaremos el gráfico.

Comencemos.

¿Para qué se usan las pirámides de población?

Es la forma más sencilla de entender la dinámica de la población de un lugar.

Es un vistazo al presente y al futuro de la población. Los jóvenes de ahora son los adultos del mañana, que a su vez serán los adultos mayores después. Entender esto de un vistazo te ayuda a proyectar la fuerza laboral, el estado de las pensiones y el futuro de las finanzas públicas.

Entre muchas otras cosas.

Este es el código para hacer una pirámide de población

Esta vez comenzaremos con el código.

Los scripts que te daré te harán el gráfico que buscas en python y R. Sólo tienes que modificar las cifras y los rangos, si es necesario.

Copia este código y úsalo en un script de python. También puedes usarlo en Google Colab.

El único módulo que necesitamos es matplotlib.

# Importamos las librerías necesarias
import matplotlib.pyplot as plt

# Definimos los datos manualmente
rangos_edades = ['0 - 5', '6 - 10', '11 - 15', '16 - 20', '21 - 25', '26 - 30', '31 - 35', '36 - 40', '41 - 45', '46 - 50', '51 - 55', '56 - 60', '61 - 65', '66 - 70', '71 - 75', '76 - 80', '81+']
hombres = [-30320, -24326, -20658, -19694, -16580, -13560, -10634, -8900, -7386, -6094, -4984, -4084, -3284, -2504, -1824, -1284, -896]
mujeres = [29144, 22493, 19878, 21686, 16947, 14374, 12220, 10800, 9634, 8056, 6804, 5634, 4512, 3500, 2642, 1904, 1208]

# Creamos la figura y los ejes
plt.figure(figsize=(10, 8))

# Graficamos la población masculina (lado izquierdo) y femenina (lado derecho)
plt.barh(rangos_edades, hombres, label='Hombres', color="#154957")
plt.barh(rangos_edades, mujeres, label='Mujeres', color="#05cd86")

# Añadimos etiquetas y título en español
plt.xlabel('Población')
plt.ylabel('Rango de Edad')
plt.title('Pirámide Poblacional para el año 1900')
plt.legend(loc='upper right')

# Mostramos el gráfico
plt.show()

Para hacer lo mismo en R, usamos este código. Nota que, como le estamos dando las cifras directamente en el código, no es necesario cargar ninguna base de datos (eso lo haremos más adelante con los datos del INEGI).

# Instalamos (si es necesario) y cargamos la librería ggplot2
if (!require(ggplot2)) install.packages("ggplot2")
library(ggplot2)

# Definimos los datos manualmente
rangos_edades <- c("0 - 5", "6 - 10", "11 - 15", "16 - 20", "21 - 25", 
                   "26 - 30", "31 - 35", "36 - 40", "41 - 45", "46 - 50", 
                   "51 - 55", "56 - 60", "61 - 65", "66 - 70", "71 - 75", 
                   "76 - 80", "81+")
hombres <- c(-30320, -24326, -20658, -19694, -16580, -13560, -10634, -8900, -7386, 
             -6094, -4984, -4084, -3284, -2504, -1824, -1284, -896)
mujeres <- c(29144, 22493, 19878, 21686, 16947, 14374, 12220, 10800, 9634, 
             8056, 6804, 5634, 4512, 3500, 2642, 1904, 1208)

# Creamos un data frame con los datos
datos <- data.frame(
  RangoEdad = factor(rangos_edades, levels = rev(rangos_edades)),  # Invertimos los niveles
  Hombres = hombres,
  Mujeres = mujeres
)

# Transformamos los datos a un formato largo para ggplot
datos_largo <- reshape2::melt(datos, id.vars = "RangoEdad", variable.name = "Genero", value.name = "Poblacion")

# Creamos la pirámide poblacional
ggplot(datos_largo, aes(x = Poblacion, y = RangoEdad, fill = Genero)) +
  geom_bar(stat = "identity", width = 0.8) +
  scale_x_continuous(labels = abs, name = "Población") +  # Etiquetas del eje x como valores absolutos
  labs(y = "Rango de Edad", title = "Pirámide Poblacional para el año 1900") +
  scale_fill_manual(values = c("Hombres" = "#154957", "Mujeres" = "#05cd86")) +  # Colores para cada género
  theme_minimal() +
  theme(legend.position = "top") +
  guides(fill = guide_legend(title = "Género"))

Debes de obtener como resultado un gráfico como este:

El truco en ambos casos es proporcionar los datos de un género en positivo y los otros en negativo.

Si ya tienes los datos y ya organizaste las sumas, basta con que cambies los números en el código y ya tienes el gráfico listo para usar.

Pero ¿qué hacer con los datos como vienen en el censo?

Hagámoslo.

Tutorial para hacer una pirámide de población con los datos del INEGI en R y Python

Normalmente no nos vamos a encontrar los datos listos para hacer nuestra gráfica.

Generalmente es necesario ordenar los datos y limpiarlos antes de comenzar a hacer los gráficos. Afortunadamente, tanto R como Python tienen funciones que facilitan mucho el trabajo. El código que te voy a pasar funciona sin cambios para el censo 2020 de México en Inegi. Si deseas usarlo en otras bases de datos, lo puedes hacer con cambios ligeros.

No te preocupes, te guiaré en el camino.

Si ya estás listo, comienza por aquí.

Paso #1: Descarga la base de datos

Para este ejemplo usaremos el censo 2020 de Inegi.

Entra el la siguiente página y descarga los tabulados del cuestionario básico de población.

Censo de Población y Vivienda 2020
Enumeración exhaustiva de la población y las viviendas existentes en el país, brinda características de ambas. Datos de 2020.

La hoja 03 contiene los datos que buscamos. Los únicos detalles son que hay que filtrar el estado que queremos que nos muestre y que nos arroja todas las edades. Para hacer una pirámide que sea fácil de leer, necesitamos dividir estos datos en rangos.

Así se ve la pantalla de los datos en Excel.

💡
En esa misma página puedes encontrar una pirámide poblacional ya hecha por INEGI en formato PDF. Puedes usarla para comparar tus resultados.

Paso #2: Carga la base de datos en Python/R

Ahora que tienes el archivo descargado, es momento de cargarlo en tu entorno de trabajo. Te mostraré cómo hacerlo tanto en Python como en R, y te explicaré cada paso para que entiendas lo que estamos haciendo y cómo puedes adaptar el código a tus necesidades.

Cargando los datos en Python

Primero, asegúrate de tener instaladas las librerías necesarias. En este caso, usaremos pandas para manejar los datos y matplotlib para las gráficas.

# Importamos las librerías necesarias
import pandas as pd
import matplotlib.pyplot as plt

Ahora, especifica la ruta al archivo que descargaste y el nombre de la hoja que contiene los datos que necesitamos (en este caso, la hoja "03").

# Especifica la ruta al archivo y el nombre de la hoja
file_path = 'ruta/a/tu/archivo.xlsx'  # Reemplaza con la ruta real de tu archivo
sheet_name = '03'  # Nombre de la hoja que contiene los datos

Leemos los datos del archivo Excel, omitiendo las primeras filas que contienen metadatos y no nos sirven para el análisis.

# Leemos la hoja de Excel, omitiendo las primeras 5 filas de metadatos
data = pd.read_excel(file_path, sheet_name=sheet_name, skiprows=5)

Renombramos las columnas para facilitar su manejo.

# Renombramos las columnas para mayor claridad
data.columns = ["Entidad", "Edad", "Poblacion_Total", "Hombres", "Mujeres", "Relacion_H_M"]

Cargando los datos en R

En R, utilizaremos el paquete readxl para leer archivos Excel y ggplot2 para las gráficas. Asegúrate de tenerlos instalados.

# Instalamos y cargamos los paquetes necesarios
if (!require("readxl")) install.packages("readxl")
if (!require("ggplot2")) install.packages("ggplot2")

library(readxl)
library(ggplot2)

Especifica la ruta al archivo y el nombre de la hoja.

# Especifica la ruta al archivo y el nombre de la hoja
file_path <- "ruta/a/tu/archivo.xlsx"  # Reemplaza con la ruta real de tu archivo
sheet_name <- "03"  # Nombre de la hoja que contiene los datos

Leemos los datos, omitiendo las primeras filas innecesarias.

# Leemos la hoja de Excel, omitiendo las primeras 5 filas de metadatos
data <- read_excel(file_path, sheet = sheet_name, skip = 5)

Renombramos las columnas.

# Renombramos las columnas para mayor claridad
colnames(data) <- c("Entidad", "Edad", "Poblacion_Total", "Hombres", "Mujeres", "Relacion_H_M")

Paso #3: Filtra y limpia los datos

Los datos que hemos cargado incluyen información de todas las entidades federativas y edades individuales. Para nuestra pirámide poblacional, vamos a enfocarnos en el nivel nacional. Pero si deseas analizar un estado específico, como Durango, te mostraré cómo hacerlo.

Filtrando los datos en Python

Primero, filtramos los datos para quedarnos solo con la entidad que nos interesa. Para el nivel nacional, la entidad se llama "Estados Unidos Mexicanos".

# Filtramos para quedarnos solo con los datos nacionales
filtered_data = data[data["Entidad"] == "Estados Unidos Mexicanos"]

Si quisieras analizar los datos de Durango, simplemente cambia el nombre de la entidad:

# Para filtrar los datos de Durango
filtered_data = data[data["Entidad"] == "Durango"]

Luego, eliminamos filas innecesarias y limpiamos la columna de edad.

# Eliminamos filas con valores NaN en 'Edad'
filtered_data = filtered_data.dropna(subset=["Edad"])

# Excluimos la fila que contiene el 'Total' de la población
filtered_data = filtered_data[filtered_data["Edad"] != "Total"]

# Eliminamos el texto ' años' de la columna 'Edad' para poder convertirla a numérico
filtered_data["Edad"] = filtered_data["Edad"].str.replace(" años", "", regex=False)

Ahora, convertimos las columnas a tipo numérico para poder trabajar con ellas.

# Convertimos las columnas a numérico
filtered_data["Edad"] = pd.to_numeric(filtered_data["Edad"], errors='coerce')
filtered_data["Hombres"] = pd.to_numeric(filtered_data["Hombres"], errors='coerce')
filtered_data["Mujeres"] = pd.to_numeric(filtered_data["Mujeres"], errors='coerce')

# Eliminamos filas con valores NaN resultantes de la conversión
filtered_data = filtered_data.dropna(subset=["Edad", "Hombres", "Mujeres"])

Filtrando los datos en R

Al igual que en Python, filtramos los datos para quedarnos con la entidad deseada.

# Filtramos para quedarnos solo con los datos nacionales
filtered_data <- subset(data, Entidad == "Estados Unidos Mexicanos")

# Si deseas los datos de Durango
filtered_data <- subset(data, Entidad == "Durango")

Eliminamos filas innecesarias y limpiamos la columna de edad.

# Eliminamos filas con NA en 'Edad'
filtered_data <- filtered_data[!is.na(filtered_data$Edad), ]

# Excluimos la fila que contiene el 'Total' de la población
filtered_data <- subset(filtered_data, Edad != "Total")

# Eliminamos el texto ' años' de la columna 'Edad' para poder convertirla a numérico
filtered_data$Edad <- gsub(" años", "", filtered_data$Edad)

Convertimos las columnas a numérico.

# Convertimos las columnas a numérico
filtered_data$Edad <- as.numeric(filtered_data$Edad)
filtered_data$Hombres <- as.numeric(filtered_data$Hombres)
filtered_data$Mujeres <- as.numeric(filtered_data$Mujeres)

# Eliminamos filas con valores NA resultantes de la conversión
filtered_data <- na.omit(filtered_data[, c("Edad", "Hombres", "Mujeres")])

💡
Nota: Convertir las columnas a numérico es esencial para poder realizar operaciones matemáticas y generar el gráfico. Si tus datos vienen en un formato diferente o contienen caracteres adicionales, es posible que necesites ajustar las funciones de limpieza.

Paso #4: Agrupa las edades en intervalos

Para hacer más legible la pirámide, agruparemos las edades en intervalos de 5 años. Si deseas usar un intervalo diferente, puedes modificar este valor.

Agrupando en Python

Creamos una nueva columna que indica el grupo de edad al que pertenece cada registro.

# Definimos el intervalo de agrupación
intervalo = 5  # Puedes cambiar este valor para intervalos diferentes

# Creamos la columna 'Grupo_Edad' con intervalos de 5 años
filtered_data["Grupo_Edad"] = (filtered_data["Edad"] // intervalo) * intervalo

Agrupamos los datos sumando las poblaciones por grupo de edad.

# Agrupamos y sumamos las poblaciones por grupo de edad
pyramid_data = filtered_data.groupby("Grupo_Edad")[["Hombres", "Mujeres"]].sum().reset_index()

Agrupando en R

Creamos la columna del grupo de edad.

# Definimos el intervalo de agrupación
intervalo <- 5  # Puedes cambiar este valor para intervalos diferentes

# Creamos la columna 'Grupo_Edad' con intervalos de 5 años
filtered_data$Grupo_Edad <- floor(filtered_data$Edad / intervalo) * intervalo

Agrupamos y sumamos.

# Agrupamos y sumamos las poblaciones por grupo de edad
library(dplyr)
pyramid_data <- filtered_data %>%
  group_by(Grupo_Edad) %>%
  summarise(Hombres = sum(Hombres), Mujeres = sum(Mujeres))

💡
Tip: Si deseas agrupar en intervalos de 10 años, simplemente cambia el valor de intervalo a 10 en el código anterior. Esto te dará grupos como 0-9, 10-19, etc.

Paso #5: Ordena los datos para el gráfico

Queremos que las edades más jóvenes aparezcan en la parte inferior de la pirámide.

Ordenando en Python

# Ordenamos los datos de mayor a menor edad para que las edades más jóvenes queden abajo
pyramid_data_sorted = pyramid_data.sort_values(by="Grupo_Edad", ascending=False)

Ordenando en R

# Ordenamos los datos de mayor a menor edad
pyramid_data <- pyramid_data %>%
  arrange(desc(Grupo_Edad))

Paso #6: Grafica la pirámide poblacional

Ahora, vamos a visualizar los datos. Te mostraré cómo personalizar el gráfico y qué aspectos puedes modificar.

Graficando en Python

Configuramos el tamaño de la figura y graficamos las barras para hombres y mujeres.

import matplotlib.pyplot as plt

# Configuramos el tamaño de la figura
plt.figure(figsize=(10, 8))

# Graficamos las barras horizontales para Hombres y Mujeres
plt.barh(pyramid_data_sorted["Grupo_Edad"], -pyramid_data_sorted["Hombres"], label="Hombres", color="#154957")
plt.barh(pyramid_data_sorted["Grupo_Edad"], pyramid_data_sorted["Mujeres"], label="Mujeres", color="#05cd86")

Personalizamos las etiquetas del eje Y para mostrar los intervalos de edad.

# Creamos etiquetas de grupo de edad
etiquetas_edad = [f"{int(edad)}-{int(edad + intervalo - 1)}" for edad in pyramid_data_sorted["Grupo_Edad"]]
plt.yticks(pyramid_data_sorted["Grupo_Edad"], etiquetas_edad)

Añadimos etiquetas y título al gráfico.

# Añadimos etiquetas y título
plt.xlabel("Población")
plt.ylabel("Grupo de Edad")
plt.title("Pirámide Poblacional")
plt.legend()

# Mostramos el gráfico
plt.tight_layout()
plt.show()

Personalización:

  • Colores: Puedes cambiar los colores modificando los valores en color. Por ejemplo, color="skyblue" para Hombres y color="pink" para Mujeres.
  • Título y etiquetas: Modifica el texto dentro de plt.title()plt.xlabel(), y plt.ylabel() para reflejar tu análisis.
  • Tamaño de la figura: Cambia el tamaño en plt.figure(figsize=(ancho, alto)) si quieres un gráfico más grande o más pequeño.

Graficando en R

Usamos ggplot2 para crear el gráfico.

library(ggplot2)

# Creamos el gráfico de la pirámide poblacional
ggplot(pyramid_data, aes(x = Grupo_Edad)) +
  # Barras para Hombres (valores negativos para orientarlas a la izquierda)
  geom_bar(aes(y = -Hombres), stat = "identity", fill = "#154957", width = intervalo - 1) +
  # Barras para Mujeres
  geom_bar(aes(y = Mujeres), stat = "identity", fill = "#05cd86", width = intervalo - 1) +
  # Configura las etiquetas de los grupos de edad
  scale_x_continuous(breaks = pyramid_data$Grupo_Edad, labels = paste0(pyramid_data$Grupo_Edad, "-", pyramid_data$Grupo_Edad + intervalo - 1)) +
  # Ajusta las etiquetas del eje Y para mostrar valores absolutos
  scale_y_continuous(labels = abs, name = "Población") +
  # Añade título y etiquetas
  labs(title = "Pirámide Poblacional", x = "Grupo de Edad") +
  # Invierte los ejes para que las edades más jóvenes estén abajo
  coord_flip() +
  theme_minimal() +
  theme(legend.position = "top")

Personalización:

  • Colores: Cambia los colores en fill dentro de geom_bar(). Por ejemplo, fill = "blue" para Hombres y fill = "red" para Mujeres.
  • Título y etiquetas: Modifica labs(title = "Tu Título", x = "Eje X", y = "Eje Y") para personalizar.
  • Tema del gráfico: Puedes cambiar el tema con theme_classic()theme_bw(), etc.
💡
Tip: Si deseas añadir una leyenda para identificar Hombres y Mujeres, puedes modificar el código para incluir fill en aes() y ajustar la leyenda con scale_fill_manual().

Paso #7: Personaliza y analiza tu pirámide

¡Felicidades! Ahora tienes una pirámide poblacional basada en los datos del INEGI.

¿Qué más puedes hacer?

  • Cambiar el intervalo de edad: Si deseas grupos más amplios o más específicos, modifica el valor de intervaloen el paso de agrupación. Por ejemplo, para intervalos de 10 años, establece intervalo = 10.
  • Seleccionar otra entidad o región: Puedes filtrar los datos para cualquier estado o municipio cambiando el nombre en el filtro inicial. Asegúrate de que el nombre coincida exactamente con el que aparece en la columna "Entidad".
  • Agregar proyecciones o datos históricos: Si tienes acceso a datos de diferentes años, puedes crear pirámides para cada año y compararlas para analizar tendencias demográficas. (Si te interesa más sobre esto, me dices y podemos expander este tutorial)
  • Personalizar el diseño del gráfico: Explora más opciones de personalización en matplotlib y ggplot2. Puedes cambiar fuentes, agregar anotaciones, ajustar escalas, entre otros.

Ejemplos de modificaciones:

En R: Cambiar el tema del gráfico.

# Cambiar el tema a clásico
theme_set(theme_classic())

En Python: Añadir una cuadrícula al gráfico.

# Añadir cuadrícula al gráfico
plt.grid(axis='x', linestyle='--', alpha=0.7)

Es tu turno de ponerlo en práctica

Las pirámides poblacionales son herramientas poderosas para entender la estructura y dinámica de una población.

Ahora puedes explorar diferentes escenarios y adaptar el análisis a lo que necesitas hacer.

Recuerda que los datos pueden venir en diferentes formatos y es posible que necesites ajustar el código para manejarlos correctamente. Experimenta y explora más funciones de las librerías que hemos usado.

Si te encuentras con algún problema o tienes dudas, contesta este post y te puedo guiar.


¡Genial! Te has registrado exitosamente.

¡Bienvenido de vuelta! Has iniciado sesión correctamente.

Te has suscrito correctamente a Marionomics: Escribe tu paper de economía.

¡Éxito! Revisa tu correo electrónico para obtener el enlace mágico para iniciar sesión.

¡Éxito! Se ha actualizado la información de facturación.

No se actualizó tu información de facturación.