#Introduccion
##Datos Los datos provienen de: https://www.ine.gov.py/microdato/encuesta-permanente-de-hogares-continua-ephc-2022-2023-2024-anual
#Procedimiento para la gestión de datos ##Acceso y descarga de datos ### Cargar las librerías necesarias y acceder
reticulate::py_install("polars")
## Using virtual environment "C:/Users/Laptop/AppData/Local/R/cache/R/reticulate/uv/cache/archive-v0/WZ05C7o-T7Nrjc1ftA_Vy" ...
## + "C:/Users/Laptop/AppData/Local/R/cache/R/reticulate/uv/cache/archive-v0/WZ05C7o-T7Nrjc1ftA_Vy/Scripts/python.exe" -m pip install --upgrade --no-user polars
import polars as pl
import os
import time
base_dir = r"C:/Users/Laptop/OneDrive/Curso Big Data/Trabajo Final"
years = [2022, 2023, 2024]
columns = ['upmm', 'nvivi', 'nhoga', 'dpto', 'area', 'anio', 'totpers', 'ingrem', 'ipcm', 'pobrezai', 'pobnopoi']
schema = {
"upmm": pl.Int32,
"nvivi": pl.Int32,
"nhoga": pl.Int32,
"dpto": pl.Utf8,
"area": pl.Utf8,
"anio": pl.Int32,
"totpers": pl.Int32,
"ingrem": pl.Int32,
"ipcm": pl.Int32,
"pobrezai": pl.Utf8,
"pobnopoi": pl.Utf8,
}
start = time.time()
dfs = []
for y in years:
path = os.path.join(base_dir, f"INGREFAM_EPHC_ANUAL_{y}.csv")
if not os.path.exists(path):
continue
try:
df = pl.read_csv(
path,
columns=columns,
schema_overrides=schema,
ignore_errors=True,
null_values=["1154522A"],
encoding="ISO-8859-1",
separator=";"
)
except Exception:
df = pl.read_csv(
path,
columns=columns,
schema_overrides=schema,
ignore_errors=True,
null_values=["1154522A"],
encoding="latin1",
separator=";"
)
dfs.append(df)
df = pl.concat(dfs) if dfs else pl.DataFrame()
output_path = os.path.join(base_dir, "ingre2022a2024polars.csv")
df.write_csv(output_path)
elapsed = time.time() - start
print(f"Tiempo total: {elapsed:.2f} s")
## Tiempo total: 0.12 s
df
| upmm | nvivi | nhoga | dpto | area | anio | totpers | ingrem | ipcm | pobrezai | pobnopoi |
|---|---|---|---|---|---|---|---|---|---|---|
| i32 | i32 | i32 | str | str | i32 | i32 | i32 | i32 | str | str |
| 14 | 10 | 1 | "Asuncion" | "Urbana" | 2022 | 2 | 7048723 | 3524362 | "No pobre" | "No pobre" |
| 14 | 20 | 1 | "Asuncion" | "Urbana" | 2022 | 2 | 5430128 | 2715064 | "No pobre" | "No pobre" |
| 14 | 22 | 1 | "Asuncion" | "Urbana" | 2022 | 5 | 9085021 | 1817004 | "No pobre" | "No pobre" |
| 14 | 24 | 1 | "Asuncion" | "Urbana" | 2022 | 10 | 27046213 | 2704621 | "No pobre" | "No pobre" |
| 14 | 25 | 1 | "Asuncion" | "Urbana" | 2022 | 1 | 2610638 | 2610638 | "No pobre" | "No pobre" |
| … | … | … | … | … | … | … | … | … | … | … |
| 28774 | 9 | 1 | "Presidente Hayes" | "Rural" | 2024 | 1 | 2391038 | 2391038 | "No Pobre" | "No pobre" |
| 28774 | 15 | 1 | "Presidente Hayes" | "Rural" | 2024 | 2 | 5728529 | 2864264 | "No Pobre" | "No pobre" |
| 28774 | 17 | 1 | "Presidente Hayes" | "Rural" | 2024 | 3 | 2988798 | 996266 | "No Pobre" | "No pobre" |
| 28774 | 19 | 1 | "Presidente Hayes" | "Rural" | 2024 | 3 | 4014357 | 1338119 | "No Pobre" | "No pobre" |
| 28774 | 22 | 1 | "Presidente Hayes" | "Rural" | 2024 | 1 | 2958417 | 2958417 | "No Pobre" | "No pobre" |
#Calcular tabla de mediana de ingresos
mediana_ipcm_anio = (
df.group_by("anio", "area", "pobnopoi")
.agg(pl.col("ipcm").median().alias("mediana_ipcm"))
.sort("anio", "area", "pobnopoi")
)
print(mediana_ipcm_anio)
## shape: (12, 4)
## ┌──────┬────────┬──────────┬──────────────┐
## │ anio ┆ area ┆ pobnopoi ┆ mediana_ipcm │
## │ --- ┆ --- ┆ --- ┆ --- │
## │ i32 ┆ str ┆ str ┆ f64 │
## ╞══════╪════════╪══════════╪══════════════╡
## │ 2022 ┆ Rural ┆ No pobre ┆ 1.176038e6 │
## │ 2022 ┆ Rural ┆ Pobre ┆ 393510.0 │
## │ 2022 ┆ Urbana ┆ No pobre ┆ 1.957431e6 │
## │ 2022 ┆ Urbana ┆ Pobre ┆ 604874.0 │
## │ 2023 ┆ Rural ┆ No Pobre ┆ 1.295947e6 │
## │ … ┆ … ┆ … ┆ … │
## │ 2023 ┆ Urbana ┆ Pobre ┆ 637874.0 │
## │ 2024 ┆ Rural ┆ No pobre ┆ 1.363462e6 │
## │ 2024 ┆ Rural ┆ Pobre ┆ 462940.0 │
## │ 2024 ┆ Urbana ┆ No pobre ┆ 2.197852e6 │
## │ 2024 ┆ Urbana ┆ Pobre ┆ 681370.0 │
## └──────┴────────┴──────────┴──────────────┘
##Añadir los datos de hombre y mujer
#import sys!{sys.executable} -m pip install "polars[excel]"
import polars as pl
# Lista de archivos
files = [
"C:/Users/Laptop/OneDrive/Curso Big Data/Trabajo Final/REG01_EPHC_ANUAL_2022.csv",
"C:/Users/Laptop/OneDrive/Curso Big Data/Trabajo Final/REG01_EPHC_ANUAL_2023.csv",
"C:/Users/Laptop/OneDrive/Curso Big Data/Trabajo Final/REG01_EPHC_ANUAL_2024.csv"
]
dfs = []
# Cargar y filtrar columnas que voy a usar
for f in files:
df = pl.read_csv(
f,
separator=";",
encoding="latin1", # ← usa latin1 porque el archivo lo requiere
infer_schema_length=0,
null_values=["", " ", "NA", "null", "NULL"],
truncate_ragged_lines=True
)
# Ajusta el nombre exacto si necesario (ver más abajo)
dfs.append(
df.select(["AÃ\x91O", "AREA", "HOMBRES", "MUJERES"])
)
# Unir todos los archivos en un solo DataFrame
df_hm = pl.concat(dfs)
# Renombrar columnas para que estén bien formateadas
df_hm = df_hm.rename({
"AÃ\x91O": "anio",
"AREA": "area",
"HOMBRES": "hombres",
"MUJERES": "mujeres"
})
# Mostrar resultado
print(df_hm)
## shape: (52_251, 4)
## ┌──────┬────────┬─────────┬─────────┐
## │ anio ┆ area ┆ hombres ┆ mujeres │
## │ --- ┆ --- ┆ --- ┆ --- │
## │ str ┆ str ┆ str ┆ str │
## ╞══════╪════════╪═════════╪═════════╡
## │ 2022 ┆ Urbana ┆ 0 ┆ 2 │
## │ 2022 ┆ Urbana ┆ 2 ┆ 0 │
## │ 2022 ┆ Urbana ┆ 0 ┆ 5 │
## │ 2022 ┆ Urbana ┆ 6 ┆ 4 │
## │ 2022 ┆ Urbana ┆ 1 ┆ 0 │
## │ … ┆ … ┆ … ┆ … │
## │ 2024 ┆ Rural ┆ 1 ┆ 0 │
## │ 2024 ┆ Rural ┆ 1 ┆ 1 │
## │ 2024 ┆ Rural ┆ 1 ┆ 2 │
## │ 2024 ┆ Rural ┆ 1 ┆ 2 │
## │ 2024 ┆ Rural ┆ 1 ┆ 0 │
## └──────┴────────┴─────────┴─────────┘
#sumarizar total hombre y mujeres
import polars as pl
files = [
"C:/Users/Laptop/OneDrive/Curso Big Data/Trabajo Final/REG01_EPHC_ANUAL_2022.csv",
"C:/Users/Laptop/OneDrive/Curso Big Data/Trabajo Final/REG01_EPHC_ANUAL_2023.csv",
"C:/Users/Laptop/OneDrive/Curso Big Data/Trabajo Final/REG01_EPHC_ANUAL_2024.csv"
]
dfs = []
for f in files:
df = pl.read_csv(
f,
separator=";",
encoding="latin1",
infer_schema_length=0,
null_values=["", " ", "NA", "null", "NULL"],
truncate_ragged_lines=True
)
dfs.append(df)
df_hm = pl.concat(dfs)
# Renombrar columnas para limpieza
df_hm = df_hm.rename({
"AÃ\x91O": "anio",
"AREA": "area",
"HOMBRES": "hombres",
"MUJERES": "mujeres"
})
# Convertir a numérico y llenar nulos
df_hm = df_hm.with_columns([
pl.col("hombres").cast(pl.Int64, strict=False).fill_null(0),
pl.col("mujeres").cast(pl.Int64, strict=False).fill_null(0)
])
# Agrupar y sumar
resumen_anio_area = (
df_hm
.group_by(["anio", "area"])
.agg([
pl.col("hombres").sum().alias("total_hombres"),
pl.col("mujeres").sum().alias("total_mujeres"),
])
.sort(["anio", "area"])
)
print(resumen_anio_area)
## shape: (6, 4)
## ┌──────┬────────┬───────────────┬───────────────┐
## │ anio ┆ area ┆ total_hombres ┆ total_mujeres │
## │ --- ┆ --- ┆ --- ┆ --- │
## │ str ┆ str ┆ i64 ┆ i64 │
## ╞══════╪════════╪═══════════════╪═══════════════╡
## │ 2022 ┆ Rural ┆ 13815 ┆ 13096 │
## │ 2022 ┆ Urbana ┆ 16796 ┆ 18205 │
## │ 2023 ┆ Rural ┆ 12749 ┆ 12316 │
## │ 2023 ┆ Urbana ┆ 15864 ┆ 17076 │
## │ 2024 ┆ Rural ┆ 12404 ┆ 12062 │
## │ 2024 ┆ Urbana ┆ 16195 ┆ 17083 │
## └──────┴────────┴───────────────┴───────────────┘
###Cruzar ambas tablas
# Asegurar que 'anio' y 'area' estén en el mismo tipo en ambas tablas (como str)
mediana_ipcm_anio = mediana_ipcm_anio.with_columns([
pl.col("anio").cast(pl.Utf8),
pl.col("area").cast(pl.Utf8)
])
resumen_anio_area = resumen_anio_area.with_columns([
pl.col("anio").cast(pl.Utf8),
pl.col("area").cast(pl.Utf8)
])
# Realizar el left join por 'anio' y 'area'
df_cruzado = mediana_ipcm_anio.join(
resumen_anio_area.select(["anio", "area", "total_hombres", "total_mujeres"]),
on=["anio", "area"],
how="left"
)
# Mostrar resultado
print(df_cruzado)
## shape: (12, 6)
## ┌──────┬────────┬──────────┬──────────────┬───────────────┬───────────────┐
## │ anio ┆ area ┆ pobnopoi ┆ mediana_ipcm ┆ total_hombres ┆ total_mujeres │
## │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
## │ str ┆ str ┆ str ┆ f64 ┆ i64 ┆ i64 │
## ╞══════╪════════╪══════════╪══════════════╪═══════════════╪═══════════════╡
## │ 2022 ┆ Rural ┆ No pobre ┆ 1.176038e6 ┆ 13815 ┆ 13096 │
## │ 2022 ┆ Rural ┆ Pobre ┆ 393510.0 ┆ 13815 ┆ 13096 │
## │ 2022 ┆ Urbana ┆ No pobre ┆ 1.957431e6 ┆ 16796 ┆ 18205 │
## │ 2022 ┆ Urbana ┆ Pobre ┆ 604874.0 ┆ 16796 ┆ 18205 │
## │ 2023 ┆ Rural ┆ No Pobre ┆ 1.295947e6 ┆ 12749 ┆ 12316 │
## │ … ┆ … ┆ … ┆ … ┆ … ┆ … │
## │ 2023 ┆ Urbana ┆ Pobre ┆ 637874.0 ┆ 15864 ┆ 17076 │
## │ 2024 ┆ Rural ┆ No pobre ┆ 1.363462e6 ┆ 12404 ┆ 12062 │
## │ 2024 ┆ Rural ┆ Pobre ┆ 462940.0 ┆ 12404 ┆ 12062 │
## │ 2024 ┆ Urbana ┆ No pobre ┆ 2.197852e6 ┆ 16195 ┆ 17083 │
## │ 2024 ┆ Urbana ┆ Pobre ┆ 681370.0 ┆ 16195 ┆ 17083 │
## └──────┴────────┴──────────┴──────────────┴───────────────┴───────────────┘
#chequear el formato
print(df_cruzado.schema)
## Schema([('anio', String), ('area', String), ('pobnopoi', String), ('mediana_ipcm', Float64), ('total_hombres', Int64), ('total_mujeres', Int64)])
###Exportar los datos de la tabla cruzada
# Define la ruta de salida
output_path = r"C:\Users\Laptop\OneDrive\Curso Big Data\Trabajo Final\resultado_cruzado.csv"
# Exporta el DataFrame a CSV
df_cruzado.write_csv(output_path)
##Gráfico
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# Convertir a Pandas
df_pd = df_cruzado.to_pandas()
# Asegurarse de que 'anio' sea string para el eje x
df_pd['anio'] = df_pd['anio'].astype(str)
# Crear el gráfico sin dividir por área
plt.figure(figsize=(8,6))
sns.barplot(data=df_pd, x='anio', y='mediana_ipcm', hue='pobnopoi')
plt.title("Mediana del IPCM por Año y Condición de Pobreza")
plt.xlabel("Año")
plt.ylabel("Mediana IPCM")
plt.xticks(rotation=45)
## ([0, 1, 2], [Text(0, 0, '2022'), Text(1, 0, '2023'), Text(2, 0, '2024')])
plt.legend(title='Condición de pobreza')
plt.tight_layout()
plt.show()
#Conclusion Los datos muestran claramente que la mediana del IPCM (Ingreso Per Cápita Mediano) varía significativamente según el área (Rural vs Urbana) y la condición de pobreza (No pobre vs Pobre) a lo largo de los años 2022 a 2024.
Diferencia por área: La mediana IPCM es consistentemente más alta en las zonas urbanas que en las rurales, para ambos grupos (pobre y no pobre). Por ejemplo, en 2022, la mediana IPCM urbana para personas no pobres es aproximadamente 1.957.431, mientras que en la rural es 1.176.038, mostrando una brecha significativa entre áreas.
Condición de pobreza: Dentro de cada área, las personas clasificadas como “No pobres” tienen una mediana IPCM mucho mayor que las personas “Pobres”. En 2022 en área rural, la mediana para no pobres es 1.176.038 en comparación con 393.510 para pobres, es decir, casi tres veces mayor.
Tendencia temporal: La mediana IPCM tanto para pobres como para no pobres aumenta en general año a año en ambas áreas. Por ejemplo, en área urbana, la mediana IPCM para no pobres crece de 1.957.431 en 2022 a 2.197.852 en 2024. Esto sugiere una mejora en los ingresos medios, aunque la brecha entre pobres y no pobres persiste.
Población total: El total de hombres y mujeres se mantiene relativamente estable en cada área y condición a lo largo del período, con números ligeramente mayores en las zonas urbanas, reflejando posiblemente una mayor concentración poblacional en estas áreas.
En resumen, aunque hay una tendencia positiva en el aumento del ingreso per cápita mediano para todos los grupos, la desigualdad sigue siendo evidente tanto entre áreas rurales y urbanas, como entre personas pobres y no pobres. Esto indica que las políticas sociales y económicas deben continuar enfocándose en reducir estas brechas para lograr un desarrollo más equitativo.