from pyLandUseMX.descargas import *
import numpy as np
import pandas as pd
import geopandas as gpd
from pathlib import Path
import requests
import osDatos del Censo
Datos de ejemplo
Aquí documentamos el procedimiento para obtener los datos a nivel manzana que se utilizan como ejemplo en Soporte
# Descargamos la geometría de las manzanas
Path(DOWNLOADS_PATH).mkdir(parents=True, exist_ok=True)
fname = 'manzanas.gpkg'
absp = os.path.abspath(os.path.join(DOWNLOADS_PATH, fname))
if os.path.exists(absp):
print("El archivo ya está descargado")
else:
url = 'https://www.dropbox.com/s/bzsj7wl4izzdbjh/manzanas_identificadores.gpkg?dl=1'
r = requests.get(url, allow_redirects=True)
open(absp, 'wb').write(r.content)
# Leemos la geometría de las manzanas de CDMX
manzanas = gpd.read_file(absp)
# Descargamos los daots del censo
Path(DOWNLOADS_PATH).mkdir(parents=True, exist_ok=True)
fname = 'censo_manzanas.zip'
absp = os.path.abspath(os.path.join(DOWNLOADS_PATH, fname))
if os.path.exists(absp):
print("El archivo ya está descargado")
else:
url = 'https://www.dropbox.com/s/hj6d2t9vtbn5qz4/censo_manzanas.zip?dl=1'
r = requests.get(url, allow_redirects=True)
open(absp, 'wb').write(r.content)
# Leemos los datos del censo (sólo unas columnas para elejemplo)
censo = pd.read_csv(absp,
dtype={'CVEGEO':str, 'colonia_cve': 'Int64'},
usecols=['CVEGEO', 'OCUPVIVPAR', 'VIVPAR_HAB'])
# Unimos
manzanas = manzanas.merge(censo, on='CVEGEO').fillna(0) # Llenamos con 0 los faltantes
manzanas = manzanas.drop(columns=['colonia_cve', 'cuadrante_id', 'colonia_nombre', 'AMBITO', 'TIPOMZA'])
manzanas.head()El archivo ya está descargado
| CVEGEO | geometry | VIVPAR_HAB | OCUPVIVPAR | |
|---|---|---|---|---|
| 0 | 0901000010898031 | POLYGON ((2790204.135 820779.247, 2790125.593 ... | 22.0 | 93.0 |
| 1 | 0901000012269024 | POLYGON ((2791387.916 821465.156, 2791376.215 ... | 0.0 | 0.0 |
| 2 | 0901000011472068 | POLYGON ((2788494.355 822775.106, 2788478.422 ... | 33.0 | 124.0 |
| 3 | 0901000011824024 | POLYGON ((2790870.494 819456.298, 2790862.256 ... | 95.0 | 340.0 |
| 4 | 0901000012377004 | POLYGON ((2792111.138 821977.886, 2792115.437 ... | 23.0 | 82.0 |
Lo guardamos
manzanas.to_file("../../datos/descargas/manzanas_ejemplo.shp")Manzanas ZMVM
Para mostrar cómo integrar datos para una Zona Metropolitana completa, vamos a hacer una integración del Censo a nivel manzana para la Zona Metropolitana del Valle de México. Para esto vamos a necesitar tres insumos básicos: el marco geoestadístico (con los datos de las geometrías de las manzanas), los datos del censo a nivel AGEB urbana y la delimitación de las zonas metropolitanas de CONAPO.
Todos los datos se pueden descargar del sitio de INEGI, para los polígonos de la delimitración de zonas urbanas, la librería provee una función para su descarga.
De aquí en adelante vamos a suponer que tenemos los archivos descargados en DOWNLOADS_PATH y que extrajimos del marco censal los datos de manzanas para los estados que nos interesan (CDMX, Hidalgo y Estado de México).
Integración de manzanas
Aquí vamos a leer las gemetrías de manzanas de cada estado, unirlas en un sólo DataFrame y seleccionar las que intersecten al polígono de la ZMVM.
# Leemos los datos (no queremos todas las columnas)
absp = os.path.abspath(os.path.join(DOWNLOADS_PATH, 'manzanas_cdmx.zip'))
manzanas_cdmx = (gpd.read_file(absp)
.drop(columns=['CVE_ENT', 'CVE_MUN', 'CVE_LOC', 'CVE_AGEB', 'CVE_MZA']))
absp = os.path.abspath(os.path.join(DOWNLOADS_PATH, 'manzanas_edomex.zip'))
manzanas_edomex = (gpd.read_file(absp)
.drop(columns=['CVE_ENT', 'CVE_MUN', 'CVE_LOC', 'CVE_AGEB', 'CVE_MZA']))
absp = os.path.abspath(os.path.join(DOWNLOADS_PATH, 'manzanas_hidalgo.zip'))
manzanas_hgo = (gpd.read_file(absp)
.drop(columns=['CVE_ENT', 'CVE_MUN', 'CVE_LOC', 'CVE_AGEB', 'CVE_MZA']))
# Concatenamos en un sólo gdf
manzanas = pd.concat([manzanas_cdmx, manzanas_edomex, manzanas_hgo])
# Descargamos los polígonos de las ciudades, seleccionamos la zmvm y seleccionamos las manzanas que intersectan al polígono.
pth = descarga_poligonos_ciudades()
zmvm = gpd.read_file(pth)
zmvm = zmvm.loc[zmvm.CVE_SUN == '13'].to_crs(manzanas.crs)
manzanas = (manzanas
.sjoin(zmvm)
.drop(columns=['index_right', 'OBJECTID', 'Shape_Leng', 'NOM_CIUDAD', 'Shape_Le_1', 'Shape_Area', 'CVE_SUN', 'SUN']))
manzanas.plot()El archivo ya está descargado
<AxesSubplot: >

Datos del censo
Ya tenemos integradas las manzanas, ahoratenemos que integrar los datos del Censo. Para el Censo de 2020 INEGI publica un csv con los resultados por AGEB y manzana urbana combinados, entonces tenemos que, además de hacer la concatenación de las bases, seleccionar únicamente los resultados a nivel manzana.
Entonces, una vez más, suponiendo que tenemos los datos guardados en la carpeta DOWNLOADS_PATH:
# Leemos el archivo
pth = os.path.abspath(os.path.join(DOWNLOADS_PATH, 'conjunto_de_datos_ageb_urbana_09_cpv2020.zip'))
censo_cdmx = pd.read_csv(pth, dtype={"ENTIDAD":str, "MUN": str, "LOC":str, "AGEB":str, "MZA": str})
# Nos quedamos sólo con las filas que tienen datos de manzanas (no localidad, agebs, etc)
censo_cdmx = censo_cdmx.loc[censo_cdmx['MZA'] != '000']
# Construimos la cvegeo de las manzanas
censo_cdmx['CVEGEO'] = censo_cdmx['ENTIDAD'] + censo_cdmx['MUN'] + censo_cdmx['LOC'] + censo_cdmx['AGEB'] + censo_cdmx['MZA']
censo_cdmx.head()| ENTIDAD | NOM_ENT | MUN | NOM_MUN | LOC | NOM_LOC | AGEB | MZA | POBTOT | POBFEM | ... | VPH_CEL | VPH_INTER | VPH_STVP | VPH_SPMVPI | VPH_CVJ | VPH_SINRTV | VPH_SINLTC | VPH_SINCINT | VPH_SINTIC | CVEGEO | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 4 | 09 | Ciudad de México | 002 | Azcapotzalco | 0001 | Azcapotzalco | 0010 | 001 | 159 | 86 | ... | 42 | 39 | 18 | 13 | 6 | * | 0 | 9 | 0 | 0900200010010001 |
| 5 | 09 | Ciudad de México | 002 | Azcapotzalco | 0001 | Azcapotzalco | 0010 | 002 | 145 | 80 | ... | 38 | 32 | 14 | 12 | 5 | 0 | 0 | 9 | 0 | 0900200010010002 |
| 6 | 09 | Ciudad de México | 002 | Azcapotzalco | 0001 | Azcapotzalco | 0010 | 003 | 124 | 64 | ... | 28 | 25 | 11 | 15 | 7 | 0 | * | 6 | 0 | 0900200010010003 |
| 7 | 09 | Ciudad de México | 002 | Azcapotzalco | 0001 | Azcapotzalco | 0010 | 004 | 158 | 83 | ... | 38 | 34 | 14 | 4 | 7 | 0 | 0 | 7 | 0 | 0900200010010004 |
| 8 | 09 | Ciudad de México | 002 | Azcapotzalco | 0001 | Azcapotzalco | 0010 | 005 | 154 | 86 | ... | 42 | 38 | 12 | 5 | 6 | 0 | 0 | 7 | 0 | 0900200010010005 |
5 rows × 231 columns
Ahora necesitamos corregir los valores nodata y usar los tipos de datos adecuados. Para eso vamos a necesitar el diccionario de datos del Censo, que también se puede descargar de su siio
fname = 'diccionario_datos_ageb_urbana_09_cpv2020.csv'
absp = os.path.abspath(os.path.join(DOWNLOADS_PATH, fname))
dicionario = pd.read_csv(absp, skiprows=3)
diccionario = (dicionario
.drop(range(0,8))
.drop(columns='Núm.')
.reset_index(drop=True)
.rename({'Mnemónico':'Nombre del Campo'}, axis=1))
diccionario| Indicador | Descripción | Nombre del Campo | Rangos | Longitud | |
|---|---|---|---|---|---|
| 0 | Población total | Total de personas que residen habitualmente en... | POBTOT | 0...999999999 | 9 |
| 1 | Población femenina | Total de mujeres que residen habitualmente en ... | POBFEM | 0...999999999 | 9 |
| 2 | Población masculina | Total de hombres que residen habitualmente en ... | POBMAS | 0...999999999 | 9 |
| 3 | Población de 0 a 2 años | Personas de 0 a 2 años de edad. | P_0A2 | 0…999999999 | 9 |
| 4 | Población femenina de 0 a 2 años | Mujeres de 0 a 2 años de edad. | P_0A2_F | 0.,.999999999 | 9 |
| ... | ... | ... | ... | ... | ... |
| 217 | Viviendas particulares habitadas que disponen ... | Viviendas particulares habitadas que tienen co... | VPH_CVJ | 0…999999999 | 9 |
| 218 | Viviendas particulares habitadas sin radio ni ... | Viviendas particulares habitadas que no cuenta... | VPH_SINRTV | 0…999999999 | 9 |
| 219 | Viviendas particulares habitadas sin línea tel... | Viviendas particulares habitadas que no cuenta... | VPH_SINLTC | 0…999999999 | 9 |
| 220 | Viviendas particulares habitadas sin computado... | Viviendas particulares habitadas que no cuenta... | VPH_SINCINT | 0…999999999 | 9 |
| 221 | Viviendas particulares habitadas sin tecnologí... | Viviendas particulares habitadas que no cuenta... | VPH_SINTIC | 0…999999999 | 9 |
222 rows × 5 columns
Ya con el diccionario podemos arreglar la base
# Codificamos los Nan
censo_cdmx = (censo_cdmx
.replace('999999999', np.nan)
.replace('99999999', np.nan)
.replace('*', np.nan)
.replace('N/D', np.nan))
# Cambiamos los tipos de datos
campos_datos = diccionario['Nombre del Campo'].unique()
censo_cdmx[campos_datos] = censo_cdmx[campos_datos].astype('float')
censo_cdmx.dtypesENTIDAD object
NOM_ENT object
MUN object
NOM_MUN object
LOC object
...
VPH_SINRTV float64
VPH_SINLTC float64
VPH_SINCINT float64
VPH_SINTIC float64
CVEGEO object
Length: 231, dtype: object
Hacemos lo mismo para Edomex e Hidalgo
# Leemos el archivo
pth = os.path.abspath(os.path.join(DOWNLOADS_PATH, 'conjunto_de_datos_ageb_urbana_13_cpv2020.zip'))
censo_hgo = pd.read_csv(pth, dtype={"ENTIDAD":str, "MUN": str, "LOC":str, "AGEB":str, "MZA": str})
# Nos quedamos sólo con las filas que tienen datos de manzanas (no localidad, agebs, etc)
censo_hgo = censo_hgo.loc[censo_hgo['MZA'] != '000']
# Construimos la cvegeo de las manzanas
censo_hgo['CVEGEO'] = censo_hgo['ENTIDAD'] + censo_hgo['MUN'] + censo_hgo['LOC'] + censo_hgo['AGEB'] + censo_hgo['MZA']
# Leemos el archivo
pth = os.path.abspath(os.path.join(DOWNLOADS_PATH, 'conjunto_de_datos_ageb_urbana_15_cpv2020.zip'))
censo_mex = pd.read_csv(pth, dtype={"ENTIDAD":str, "MUN": str, "LOC":str, "AGEB":str, "MZA": str})
# Nos quedamos sólo con las filas que tienen datos de manzanas (no localidad, agebs, etc)
censo_mex = censo_mex.loc[censo_mex['MZA'] != '000']
# Construimos la cvegeo de las manzanas
censo_mex['CVEGEO'] = censo_mex['ENTIDAD'] + censo_mex['MUN'] + censo_mex['LOC'] + censo_mex['AGEB'] + censo_mex['MZA']
# Codificamos los Nan
censo_hgo = (censo_hgo
.replace('999999999', np.nan)
.replace('99999999', np.nan)
.replace('*', np.nan)
.replace('N/D', np.nan))
censo_hgo[campos_datos] = censo_hgo[campos_datos].astype('float')
censo_mex = (censo_mex
.replace('999999999', np.nan)
.replace('99999999', np.nan)
.replace('*', np.nan)
.replace('N/D', np.nan))
censo_mex[campos_datos] = censo_mex[campos_datos].astype('float')Concatenamos y unimos a las geometrías que calculamos arriba
censo = pd.concat([censo_cdmx, censo_hgo, censo_mex])
manzanas = (manzanas
.merge(censo, on='CVEGEO')
.drop(columns=['ENTIDAD', 'NOM_ENT', 'MUN', 'NOM_MUN', 'LOC', 'NOM_LOC', 'AGEB', 'MZA']))
manzanas.head()| CVEGEO | AMBITO | TIPOMZA | geometry | POBTOT | POBFEM | POBMAS | P_0A2 | P_0A2_F | P_0A2_M | ... | VPH_TELEF | VPH_CEL | VPH_INTER | VPH_STVP | VPH_SPMVPI | VPH_CVJ | VPH_SINRTV | VPH_SINLTC | VPH_SINCINT | VPH_SINTIC | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0901000010898031 | Urbana | Típica | POLYGON ((2790204.135 820779.247, 2790125.593 ... | 93.0 | 56.0 | 37.0 | 4.0 | NaN | 3.0 | ... | 20.0 | 19.0 | 15.0 | 16.0 | 6.0 | 3.0 | 0.0 | 0.0 | 7.0 | 0.0 |
| 1 | 0901000012269024 | Urbana | Típica | POLYGON ((2791387.916 821465.156, 2791376.215 ... | 6.0 | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 2 | 0901000011472068 | Urbana | Típica | POLYGON ((2788494.355 822775.106, 2788478.422 ... | 124.0 | 66.0 | 58.0 | 3.0 | 3.0 | 0.0 | ... | 25.0 | 29.0 | 25.0 | 22.0 | 9.0 | 8.0 | 0.0 | NaN | 7.0 | 0.0 |
| 3 | 0901000011824024 | Urbana | Típica | POLYGON ((2790870.494 819456.298, 2790862.256 ... | 340.0 | 177.0 | 163.0 | 12.0 | 8.0 | 4.0 | ... | 54.0 | 90.0 | 69.0 | 56.0 | 29.0 | 14.0 | NaN | NaN | 25.0 | NaN |
| 4 | 0901000012377004 | Urbana | Típica | POLYGON ((2792111.138 821977.886, 2792115.437 ... | 82.0 | 41.0 | 41.0 | NaN | 0.0 | NaN | ... | 15.0 | 21.0 | 13.0 | 13.0 | 6.0 | 3.0 | 0.0 | 0.0 | 9.0 | 0.0 |
5 rows × 226 columns
Aquí ya tenemos todas las manzanas unidas y con datos. Ya sólo hay que exportar.
manzanas.to_file("../../datos/descargas/manzanas_datos.gpkg", layer='manzanas')