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.
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
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)
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)