Análisis

Implementaciones de métodos y algoritmos para analizar el uso de suelo y la estructura urbana.

Market Basket

El análisis de Canasta de Mercado (o análisis de afinidad) busca encontrar patrones de co-ocurrencia en bases de transacciones. En el caso geográfico, vamos a considerar como transacciones a las unidades espaciales que estemos usando (elementos de una malla, colonias, agebs, etc) y vamos a buscar co-ocurrencias de usos o actividades en nuestras unidades.

En general, el análisis de afinidad se divide en dos etapas: la extracción de patrones frecuentes (co-ocurrencias) y la generación de reglas de asosiación a partir de estos patrones. Para la implementación del análisis en esta librería vamos a usar las funciones del paquete mlxtend.

El punto de entrada es la Clase Canasta, que contiene tanto los puntos que representan nuestras actividades (equivalentes a los items en la lista de compras) como los polígonos en los que vamos a agregar las transacciones.

Nota: Por lo pronto sólo está implementada usando un soporte de la clase Malla


source

Canasta

 Canasta (puntos:geopandas.geodataframe.GeoDataFrame,
          cobertura:pyLandUseMX.usodesuelo.Soporte)

Clase para guardar los elementos básicos del análisis de afinidad.

Type Details
puntos GeoDataFrame Los puntos que representan las actividades o items
cobertura Soporte Los polígonos en los que se agregan los items
Returns None

Para ver cómo funciona, vamos a cagar los datos de ejemplo del DENUE, agregarlos por categoría y luego seleccionar únicamente la categoría de Comercio

pth = descarga_denue(tipo='ejemplo')
denue = Denue.desde_archivo(pth)
categorias = {
    'Manufacturas': ['^31.*5$', '^32.*5$', '^33.*5$'],
    'Oficinas': ['^51', '^521', '^523', '^524', '^5312', '^5313', '^541', '^55'],
    'Comercio': ['^46[123456]']
}
usos = denue.agrega_en_usos(categorias)
comercio = usos.datos.loc[usos.datos.Categoria == 'Comercio']
comercio.head()
El archivo ya está descargado
nom_estab raz_social codigo_act nombre_act per_ocu tipoCenCom cve_ent cve_mun cve_loc ageb ... index_right OBJECTID Shape_Leng NOM_CIUDAD Shape_Le_1 Shape_Area CVE_SUN SUN geometry Categoria
1 TIENDA NATURISTA EL ARTE DE LA NATURALEZA None 464113 Comercio al por menor de productos naturistas,... 0 a 5 personas None 09 007 0001 1814 ... 53 54 630172.981156 Valle de México 630.172981 781912.110166 13 13.0 POINT (-99.06312 19.33782) Comercio
3 SIN NOMBRE None 461130 Comercio al por menor de frutas y verduras fre... 0 a 5 personas None 09 008 0001 0423 ... 53 54 630172.981156 Valle de México 630.172981 781912.110166 13 13.0 POINT (-99.25436 19.30129) Comercio
6 ABARROTES LA TIA None 461110 Comercio al por menor en tiendas de abarrotes,... 0 a 5 personas None 15 121 0001 1763 ... 53 54 630172.981156 Valle de México 630.172981 781912.110166 13 13.0 POINT (-99.19269 19.58976) Comercio
7 BIZUTERIA SIN NOMBRE None 463215 Comercio al por menor de bisutería y accesorio... 0 a 5 personas None 15 122 0001 0847 ... 53 54 630172.981156 Valle de México 630.172981 781912.110166 13 13.0 POINT (-98.94058 19.31219) Comercio
8 FRUTAS Y VERDURAS SIN NOMBRE None 461130 Comercio al por menor de frutas y verduras fre... 0 a 5 personas None 15 060 0001 1037 ... 53 54 630172.981156 Valle de México 630.172981 781912.110166 13 13.0 POINT (-99.33855 19.61941) Comercio

5 rows × 21 columns

Ahora construimos la malla a partir de estos puntos e instanciamos la clase

malla = Malla.desde_capa(comercio.to_crs(32614), 1000)
canasta = Canasta(comercio, malla)
canasta
<__main__.Canasta>

Asociar capas

Para asociar los puntos a la malla, la clase Canasta implementa el método asocia, que utiliza por debajo el método agrega_puntos de la clase Malla


source

Canasta.asocia

 Canasta.asocia (campo:str)
Type Details
campo str Columna de puntos que clasifica a las observaciones
Returns Canasta

Vamos a asociar los puntos a la malla usando la columna codigo_act para obtener todas las ocurrencias de cada actividad en cada elemento de la malla.

asociada = canasta.asocia('codigo_act')
asociada.malla.datos.head()
grid_id 461110 461121 461122 461123 461130 461140 461150 461160 461170 ... 466114 466211 466212 466311 466312 466313 466314 466319 466410 geometry
0 0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 POLYGON ((449355.857 2095991.537, 450355.857 2...
1 1 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 POLYGON ((449355.857 2096991.537, 450355.857 2...
2 2 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 POLYGON ((449355.857 2097991.537, 450355.857 2...
3 3 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 POLYGON ((449355.857 2098991.537, 450355.857 2...
4 4 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 POLYGON ((449355.857 2099991.537, 450355.857 2...

5 rows × 65 columns

Codificar transacciones

En su implementación más sencilla, el análisis de afinidad sólo toma en cuenta la ocurrencia de un item en cada transacción, sin importar la cantidad de items. Para eso, la clase Canasta implementa el método codifica_transaccion que simplemente captura a través de un booleano la existencia de cada item en cada renglón.


source

Canasta.codifica_transaccion

 Canasta.codifica_transaccion ()

Este método regresa un DataFrame con booleanos que representan la existencia de cada _item__ en cada unidad espacial. Noten que perdemos la geometría de la malla pero conservamos el identificador (grid_id) para unirlo después.

Nota: Este método debe aplicarse despues de asociar, de lo contrario se arroja error

codificada = asociada.codifica_transaccion()
codificada.head()
461110 461121 461122 461123 461130 461140 461150 461160 461170 461190 ... 466113 466114 466211 466212 466311 466312 466313 466314 466319 466410
grid_id
0 False False False False False False False False False False ... False False False False False False False False False False
1 False False False False False False False False False False ... False False False False False False False False False False
2 False False False False False False False False False False ... False False False False False False False False False False
3 False False False False False False False False False False ... False False False False False False False False False False
4 False False False False False False False False False False ... False False False False False False False False False False

5 rows × 63 columns

Este resultado ya se le puede dar como entrada a cualquier algoritmo de asociación de mlxtend. En este caso vamos a usar apriori

asociaciones = apriori(codificada, min_support=0.07, use_colnames=True)
asociaciones
support itemsets
0 0.217446 (461110)
1 0.077583 (461121)
2 0.096881 (461122)
3 0.098830 (461130)
4 0.094347 (461160)
5 0.085185 (463211)
6 0.088109 (464111)
7 0.148343 (465311)
8 0.075634 (461121, 461110)
9 0.093177 (461122, 461110)
10 0.094444 (461130, 461110)
11 0.088402 (461160, 461110)
12 0.078460 (463211, 461110)
13 0.084016 (464111, 461110)
14 0.138402 (465311, 461110)
15 0.077096 (461122, 465311)
16 0.076121 (461130, 465311)
17 0.073099 (461160, 465311)
18 0.076023 (461122, 465311, 461110)
19 0.074659 (461130, 465311, 461110)
20 0.071735 (461160, 465311, 461110)