En esta práctica vamos a explorar la forma en la que agregación de los datos influye en los resultados de un análisis. Para esto vamos a trabajar con los datos de desaparecidos en la República Mexicana entre 2006 y 2014.
Los datos vienen en dos ShapeFiles, uno a nivel estatal y otro a nivel municipal. Importemos los archivos con GeoPandas
para analizarlos:
from geopandas import GeoDataFrame
estatal = GeoDataFrame.from_file('data/des_rezago_estado.shp')
municipal = GeoDataFrame.from_file('data/muns_geo_des.shp')
Analicemos los datos un poco:
estatal.head()
Debido a que estos datos poseen 22 columnas, no es posible verlos sencillamente; como tal, vamos a listar las columnas para ver qué datos se tienen:
estatal.info()
En las columnas 2006 a 2014 tenemos los datos de desaparecidos para cada año. En las demás columnas tenemos alguna información sobre las condiciones socioeconómicas de cada Unidad Espacial:
El mismo proceso puede ser repetido para el GeoDataFrame
en la variable municipal
; primero, analizando la apariencia del mismo:
municipal.head()
Y después, a través de la función .info()
, que nos permite observar que se tienen el mismo tipo de variables:
municipal.info()
En el primer ejercicio, vamos a realizar una Regresión Lineal del Total de Desaparecidos (sobre cada uno de los años), contra alguna variable socioeconómica para observar cómo cambia el resultado con la escala del análisis.
El primer paso es crear y calcular una columna con el Total de Desaparecidos; para esto, primero se aislan en un DataFrame
nuevo las columnas que nos interesan:
des_estado = estatal[['cvegeo','2006','2007','2008','2009','2010','2011','2012','2013','2014']]
des_estado.head()
Para después realizar la suma por fila utilizando la función .sum()
y guardando el resultado en una nueva columna llamada total_des
:
des_estado['total_des'] = des_estado.sum(axis=1)
des_estado.head()
Esta nueva columna puede ser añadida a los datos originales, a través de la función .merge()
de la librería pandas
:
import pandas as pd
estatal = pd.merge(estatal, des_estado[['total_des','cvegeo']] , on = 'cvegeo' )
estatal.head()
Lo mismo se repite para los municipios:
# Crear un DataFrame nuevo con sólo las columnas para el cálculo
des_mun = municipal[['cvegeo_x','2006','2007','2008','2009','2010','2011','2012','2013','2014']]
# Realizar la suma
des_mun['total_des'] = des_mun.sum(axis=1)
# Generar la unión de la nueva columna a los datos originales
municipal = pd.merge(municipal, des_mun[['total_des','cvegeo_x']] , on = 'cvegeo_x' )
# Analizar los datos para verificar el proceso
municipal.head()
Para empezar, podemos suponer que la cantidad de desaparecidos puede estar correlacionada con la cantidad de habitantes de una zona. Probemos modelar esto a nivel estatal con una Regresión Lineal Simple, utilizando la librería statsmodels
para esto:
# Importar biblioteca a utilizar
import statsmodels.formula.api as sm
# Generar el modelo a través de Mínimos Cuadrador Ordinarios
model = sm.ols('total_des ~ POB1', data = estatal)
# Realizar formalmente la Regresión Lineal
result = model.fit()
# Observar los resultados
result.summary()
El primero comando importa la biblioteca a utilizar para realizar las regresiones; el segundo genera el modelo de Mínimos Cuadrados Ordinarios (OLS, por sus siglas en inglés) a través de la función .ols()
; después, se genera formalmente la regresión lineal a través de la función .fit()
, para finalizar con la visualización del modelo utilizando .summary()
:
Analizando los resultados es posible observar que, aunque la relación entre el Total de Desaparecidos (total_des
) y la Población del Estado (POB1
) es significativa, pues la significancia del coeficiente asociada es menor al 10% (Observable en P>|t|
), la regresión explica muy poco del fenómeno, dado el valor del estadístico $R^2$ (Adj. R-squared
).
Resulta pertinente preguntarse, ¿sucederá lo mismo a nivel municipal? Pueden repetirse el mismo grupo de comandos que en el caso estatal:
# Importar biblioteca a utilizar
import statsmodels.formula.api as sm
# Generar el modelo a través de Mínimos Cuadrador Ordinarios
model = sm.ols('total_des ~ POB1', data = municipal)
# Realizar formalmente la Regresión Lineal
result = model.fit()
# Observar los resultados
result.summary()
En este caso, no sólo el coeficiente de POB1
se vuelve mucho más significativo, siéndolo al 1%, sino también el valor del estadístico $R^2$, indica que esta relación, modelada a nivel municipal, explica mucho más que al momento de modelarla a nivel estatal.
Realicen múltiples regresiones, utilizando diferentes variables que consideren puedan explicar la cantidad de desaparecidos. Comparen los resultados a nivel Estatal y Municipal
También podemos pensar en modelos un poco más complicaos; por ejemplo, las Regresiones Multivariadas. En un primer experimento, podemos modelar la cantidad de desaparecidos a partir de la Población Total y el Índice de Rezago. Realizando esto a nivel estatal:
model = sm.ols('total_des ~ POB1 + rezago', data = estatal)
result = model.fit()
result.summary()
Es posible observar que, entre las advertencias arrojadas por statsmodels
, se nos avisa que existe un Número de Condición demasiado grande, lo cual puede relacionarse a un problema de Multicolinealidad entre las variables; esto es, algunas de nuestras variables se encuentran muy correlacionadas y, por lo tanto, no deberían de utilizarse juntas en este modelo.
Para determinar si éste es el caso, podemos examinar la Matriz de Correlación de la variables; en particular, los eigenvalores de la misma, para verificar si tenemos Multicolinealidad:
# Importar la nueva librería a utilizar
import numpy as np
# Generar la Matriz de Colinearidad (Notar que existen dos pares de corchetes)
corr = estatal[['POB1', 'rezago', 'total_des']].corr()
# Obtener los Eigenvalores de la matriz (w son Eigenvalores, v Eigenvectores)
w , v = np.linalg.eig(corr)
# Visualizar el resultado
w
Lo que hicimos aquí fue importar la librería numpy
que incluye métodos de Álgebra Líneal; después, calculamos la Matriz de Correlación a través de pandas
y, finalmente, calculamos los eigenvalores de dicha matriz.
Debido a que ninguno de los eigenvalores es cercano a cero, podemos concluir que no tenemos problemas de multicolinealidad y, por lo tanto, la advertencia de un Número de Condición grande se debe a problemas numéricos
En este caso, podemos pensar que estos problemas se derivan del hecho de que la variable POB1
posee valores mucho más grandes que el resto. Para resolver este problema, intentemos reescalar las variables:
# Aislar en un nuevo DataFrame las variables de interés
vars_estatal = estatal[['POB1','rezago','total_des']]
# Normalizar las variables
vars_estatal_norm = (vars_estatal - vars_estatal.mean()) / (vars_estatal.std())
# Obtener los estadísticos descriptivos a través de .describe()
vars_estatal_norm.describe()
Lo que hicimos aquí fue reescalar los valores de nuestras variables utilizando la fórmula:
$$ z_i = \dfrac{y - \bar{y}}{\sigma_y} $$Donde $z_i$ es la versión estandarizada de nuestra variable, $\bar{y}$ es el promedio de la misma y $\sigma$ su desviación estándar; esto consigue que la media se encuentre centrada en cero, y lo que cuantificamos es la desviación de esta media con respecto al rango.
Ahora, veamos si esta transformación de datos nos ayuda a resolver el problema del Número de Condición:
model = sm.ols("total_des ~ POB1 + rezago", data = vars_estatal_norm)
result = model.fit()
result.summary()
Como puede observarse, el problema ha sido resuelto; como tal, ahora se tiene un Número de Condición perfectamente aceptable y, por lo tanto, podemos tener confianza en nuestros resultados.
Repliquemos este proceso para la escala municipal:
# Aislar las variables de interés
vars_municipal = municipal[['POB1','rezago','total_des']]
# Normalizar las variables
vars_municipal_norm = (vars_municipal - vars_municipal.mean()) / (vars_municipal.std())
# Generar el modelo a través de Mínimos Cuadrados Ordinarios
model = sm.ols("total_des ~ POB1 + rezago", data = vars_municipal_norm)
# Realizar la Regresión Lineal
result = model.fit()
# Visualizar los resultados del proceso
result.summary()
En estos modelos de Regresión Lineal Multivariada, estamos observando que, mientras a Nivel Estatal el valor de $R^2$ es de 0.031, indicando que se explica menos del 5% del fenómeno, en el caso municpal es de 0.36, ¡un orden de magnitud más grande! Además, la significancia del Índice de Rezago (valor de su coeficiente) es mucho mayor para el caso municipal a comparación del caso estatal.
¿Qué quiere decir esto? ¿Cuál es la verdadera influencia del Índice de Rezago en la cantidad de desaparecidos?
Uilicen diferentes combinaciones de las variables disponibles para tratar de explicar mejor el Total de Desaparecidos. Repitan sus ejercicios a Nivel Estatal y Municipal; recuerden que es necesario reescalar los datos.
Hasta el momento hemos trabajado con los datos del Total de Desaparecidos; cabe preguntarse, ¿el resultado sería muy diferente si se trabajan con tasas en lugar de los valores brutos?.
Repitamos los ejercicios anteriores utilizando ahora, como Variable Dependiente, la Tasa de Desaparecidos por cada 100,000 habitantes. El primer paso es, por supuesto, calcular dicha tasa y agregala como columna a los datos originales:
tasa = estatal['total_des'].divide(estatal['POB1'])*100000
tasa.head()
Aunque la sintaxis es un poco extraña, lo que estamos haciendo es realmente sencillo: la columna total_des
de los datos originales está siendo dividida por la columna POB1
, elemento por elemento.
Es importante resaltar que el resultado no es un DataFrame
, sino un objeto del tipo Series
, que resulta ser más simple en términos de que sólo tiene una columna y un índice. Para poder unir el resultado a los datos originales, necesitamos convertir el objeto Series
a un DataFrame
, y proceder de la misma forma que se hizo con el Total de Desaparecidos, esto es, utilizar la función .merge()
:
# Convertir la serie en un DataFrame
tasa_df = pd.DataFrame(tasa,columns=['tasa'])
# Realizar la unión a través de .merge() y utilizando los índices
estatal = pd.merge(estatal,tasa_df,left_index=True, right_index=True)
# Verificar el proceso
estatal.head()
A diferencia de los casos anteriores, dentro de la función .merge()
utilizamos los índices de cada DataFrame
como las llaves para la unión, a través de los argumentos left_index
y right_index
; esto pues ya no existen columnas en común, pero sabemos que los datos se encuentran bien ordenados.
La primera pregunta a realizar es si esta Tasa de Desaparecidos se encuentra correlacionada con la Población Total; para esto, repetimos el proceso realizado anteriormente:
# Generar la Matriz de Colinearidad)
corr = estatal[['POB1', 'total_des', 'tasa']].corr()
# Obtener los Eigenvalores de la matriz
w , v = np.linalg.eig(corr)
# Visualizar el resultado
w
Otra forma de verificar la existencia de Multicolinearidad es observando directamente la Matriz de Correlación generada:
corr
Puede observarse que la correlación entre la Población Total y la Tasa de Desaparecidos es mucho más cercana a cero que la correlación entre la Población Total y el valor bruto del Total de Desaparecidos. Esto nos permite concluir que, como era de esperarse, la influencia de la Población Total sobre la tasa es menor que sobre el valor bruto. Pregunta - ¿Por qué ocurre esto?
Hecho lo anterior, podemos volver a correr nuestros modelos utilizando el proceso repetido anteriormente:
# Aislar las variables de interés
vars_estatal = estatal[['POB1','rezago','tasa']]
# Normalizar las variables
vars_estatal_norm = (vars_estatal - vars_estatal.mean()) / (vars_estatal.std())
# Generar el modelo por Mínimos Cuadrados Ordinarios
model = sm.ols("tasa ~ POB1 + rezago", data = vars_estatal_norm)
# Formalizar la Regresión Lineal
result = model.fit()
# Observar el resultado
result.summary()
¡Ahora no explicamos absolutamente nada de la variable dependiente!
¿Qué es lo que ocurre a Nivel Municipal?
tasa = municipal['total_des'].divide(municipal['POB1'])*100000
tasa_df = pd.DataFrame(tasa,columns=['tasa'])
tasa_df.head()
municipal = pd.merge(municipal,tasa_df,left_index=True, right_index=True)
vars_municipal = municipal[['POB1','rezago','total_des','tasa']]
vars_municipal_norm = (vars_municipal - vars_municipal.mean()) / vars_municipal.std()
model = sm.ols(formula="tasa ~ POB1 + rezago",data=vars_municipal_norm)
result = model.fit()
result.summary()
Aunque el modelo se vuelve un poco más explicativo, aún no podemos asegurar que éste sea válido, ni a Nivel Estatal ni Municipal.
Planteen un modelo usando las variables disponibles que explique mejor las Tasas de Desaparecidos. Al igual que en el ejercicio anterior, repitan el análisis para ambas escalas.
En la primera parte de la práctica, vimos cómo la Escala de Análisis tiene influencia sobre los resultados del mismo. En esta segunda parte vamos a estudiar cómo diferentes formas de agregar los datos, en una misma escala, también puede tener influencia sobre los resultados del análisis.
En esta segunda parte, se trabajará con los datos de mezcla de Usos de Suelo de la Ciudad de México, y se estimará su efecto en la Generación de Viajes. Los datos de Uso de Suelo están calculados a partir del DENUE, mientras que la información sobre los viajes proviene de la Encuesta Origen-Destino 2007 de INEGI, por lo que la Escala de Análisis serán los Distritos de Tráfico de dicha encuesta.
Como siempre, el primer paso es leer y revisar los datos:
from geopandas import GeoDataFrame
datos = GeoDataFrame.from_file('data/distritos_variables.shp')
datos.head()
El ShapeFile
que leímos tiene columnas para cada uno de los tipos de Uso de Suelo que nos interesan (Vivienda, Comercio, Servicios y Ocio); adicionalmente, tiene tres columnas con información de los viajes:
Por otra parte, la mezcla de Usos de Suelos es medida utilizando el Índice de Entropía, el cual se calcula de acuerdo a la siguiente fórmula:
$$ E = \sum\limits_{j}{\frac{p_{j}*ln(p_{j})}{ln(J)}} $$Donde $p_j$ representa la proporción del $j-ésimo$ Uso de Suelo con respecto al total, y $J$ es el número total de Usos de Suelo. A continuación se presentan los comandos para calcular este índice, los cuales requieren de la librería numpy
:
# Importar la biblioteca a utilizar
import numpy as np
# Crear variable 'intensidad', suma de todos los Usos de Suelo
intensidad = datos['comercio'] + datos['viv'] + datos['ocio'] + datos['servicios']
# Calcular las proporciones para cada Uso de Suelo
prop_comercio = datos['comercio'] / intensidad
prop_viv = datos['viv'] / intensidad
prop_ocio = datos['ocio'] / intensidad
prop_servicios = datos['servicios'] / intensidad
# Utilizar la fórmula del Índice de Entropía
entropia = (prop_comercio*np.log(prop_comercio) + prop_viv*np.log(prop_viv) + prop_ocio*np.log(prop_ocio)
+ prop_servicios*np.log(prop_servicios))/np.log(4)
# Visualizar el resultado
entropia.head()
Lo que hicimos para calcular la Entropía es relativamente sencillo; primero, creamos la variable intensidad
, que es la suma de todos los Usos de Suelo; luego, fuimos calculando cada una de las proporciones asociadas a cada uso de suelo; finalmente, sumamos estas proporciones y las dividimos por el logaritmo natural del total de Usos de Suelo en el distrito.
Lo que se obtiene es un objeto del tipo Series
, que contiene los Índices de Entropía de forma ordenada; ahora, es necesario unir esta serie a los datos originales:
datos['entropia'] = entropia
datos.head()
Ahora que ya se tienen todos los datos, probemos un modelo que intente explicar la cantidad de viajes que terminan en cada distrito. Lo pimero que vamos a hacer es explorar la colinearidad de las variables que tenemos:
corr = datos[['ocio','comercio','servicios','viv','entropia']].corr()
w, v = np.linalg.eig(corr)
w
Debido a que se tienen eigenvalores cercanos al cero, parece que existirán problemas de colinearidad; como tal, para seleccionar las variables entre las cuales existe este problema, observamos directamente la Matriz de Correlación:
corr
Como pueden ver, la Entropia guarda bastante correlación con el resto de las variables, sobre todo con las de Comercio y Ocio; como tal, por lo pronto, seleccionemos únicamente Entropía y Vivienda como variables explicativas.
Antes de generar el modelo, normalicemos las variables, pues éstas tienen escalas de variación muy diferentes, y ya sabemos que esto puede traer problemas:
variables = datos[['entrada','viv','entropia']]
vars_norm = (variables - variables.mean())/variables.std()
vars_norm.describe()
Con las variables seleccionadas y normalizadas, es posible correr un primer modelo utilizando la biblioteca statsmodels
:
import statsmodels.formula.api as sm
model = sm.ols(formula="entrada ~ viv + entropia",data=vars_norm).fit()
model.summary()
Especifiquen diferentes modelos para tratar de explicar cada una de las tres variables de viajes en los distritos.
Ahora, vamos a cambiar de escala de análisis, agregando los distritos en unidades más grandes. Para esto, puede utilizarse una biblioteca de Python llamadaclusterpy
, la cual ayuda a generar regionalizaciones al azar a partir de los datos; sin embargo, esta librería únicamente es soportada en las versiones de Python 2.X, y descontinuada para las versiones más recientes de Python 3.X.
Como tal, únicamente se importará un ejemplo del resultado de esta librería, la cual ya se encuentra presete en los datos de trabajo:
datos_cp = GeoDataFrame.from_file('data/randmo_1.shp')
Primero, se analizan las columnas presentes en el nuevo GeoDataFrame
:
datos_cp.info()
La única variable diferente que sobresalta en la llamada random_2016
, que es donde la biblioteca clusterpy
almacena el identificador de las regiones al azar que ha generado. Como tal, ahora necesitamos colocar este identificador en los datos originales, utilizando la columna cve_dist
como llave para realizar la unión a través de la función .merge()
:
# Aislar las columnas de interés para la unión
tmp = datos_cp[['cve_dist', 'random_2016']]
# Unir el Identificador de Región a los datos originales
datos = pd.merge(datos, tmp, on='cve_dist')
# Renombrar la columna del identificador
datos = datos.rename(columns = {'random_2016':'id_region'})
# Verificar el proceso
datos.head()
Ahora ya se tiene casi todo lo necesario para correr un nuevo modelo, esta vez sobre las variables agregadas en regiones; lo único que hace falta es, justamente, calcular estas variables agregadas, lo cual puede hacerse a través de la función .groupby()
de pandas
:
agregados = datos.groupby(by = 'id_region').sum()
agregados.head()
Aquí simplemente agrupamos los datos según la columna id_region
, y calculamos la suma de las variables sobre cada grupo; el único problema es que la Entropía permanece calculada como la suma de las entropias individuales, lo cual no es de utilidad. Como tal, es necesario volver a calcular el Índice de Entropia:
# Crear variable 'intensidad', suma de todos los Usos de Suelo
intensidad = agregados['comercio'] + agregados['viv'] + agregados['ocio'] + agregados['servicios']
# Calcular las proporciones para cada Uso de Suelo
prop_comercio = agregados['comercio'] / intensidad
prop_viv = agregados['viv'] / intensidad
prop_ocio = agregados['ocio'] / intensidad
prop_servicios = agregados['servicios'] / intensidad
# Utilizar la fórmula del Índice de Entropía
entropia = (prop_comercio*np.log(prop_comercio) + prop_viv*np.log(prop_viv) + prop_ocio*np.log(prop_ocio)
+ prop_servicios*np.log(prop_servicios))/np.log(4)
# Añadir el nuevo cálculo al DataFrame
agregados['entropia'] = entropia
# Visualizar el resultado
agregados.head()
Ahora es posible correr el mismo modelo que en los ejemplos anteriores, esta vez utilizando los datos agregados. Cabe recordar que, antes que nada, es necesario normalizarlos:
# Aislar las variables a normalizar
variables = agregados[['entrada', 'viv', 'entropia']]
# Normalizar las variables
vars_norm = (variables - variables.mean()) / variables.std()
# Generar la Regresión Lineal por Mínimos Cuadrados Ordinarios
model = sm.ols('entrada ~ viv + entropia' , data = vars_norm).fit()
# Visualizar el resultado de la regresión
model.summary()
Ahora, el objetivo es comparar los resultados anteriores con los generados a partir de diferentes regionalizaciones aleatorias de los mismos datos. En la siguiente celda es posible observar este proceso; todos los comandos utilizados anteriormente se repiten, siendo la única diferencia que de las Líneas 1 a 11 se generan números al azar como Identificadores de Región, a través de la función .random()
de la biblioteca numpy
, los cuales son reasignados a los datos originales para volver a generar la Regresión Lineal:
# Importar biblioteca que se utilizará en el proceso
import math
# Generar una serie con Identificadores de Regiones asignados al azar
rndm = pd.Series()
for x in range(len(datos)):
rndm.loc[x] = math.floor(np.random.random()*(49+1))
# Colorcar los nuevos identificadores en los datos originales y agrupar
datos['id_region'] = rndm
agregados = datos.groupby(by = 'id_region').sum()
# Recalcular el Índice de Entropía según las nuevas regiones
intensidad = agregados['comercio'] + agregados['viv'] + agregados['ocio'] + agregados['servicios']
prop_comercio = agregados['comercio'] / intensidad
prop_viv = agregados['viv'] / intensidad
prop_ocio = agregados['ocio'] / intensidad
prop_servicios = agregados['servicios'] / intensidad
entropia = (prop_comercio*np.log(prop_comercio) + prop_viv*np.log(prop_viv) + prop_ocio*np.log(prop_ocio)
+ prop_servicios*np.log(prop_servicios))/np.log(4)
agregados['entropia'] = entropia
# Volver a generar la Regresión Lineal según las nuevas regiones
variables = agregados[['entrada', 'viv', 'entropia']]
vars_norm = (variables - variables.mean()) / variables.std()
model = sm.ols('entrada ~ viv + entropia' , data = vars_norm).fit()
# Visualizar el resultado
model.summary()
Como pueden ver, cada vez que corran la celda anterior, van a tener un resultado un poco diferente, es decir, cada modelo arroja modelos diferentes en la misma escala. En este caso, podemos pensar que no se trata de un problema muy grave, pues nosotros sabemos que las agregaciones son aleatorias y tenemos alguna certeza de que las desviaciones observadas en los resultados son de igual forma aleatorias.
Sin embargo, cabe preguntar, ¿qué pasa cuando no tenemos control sobre las agregaciones?
Encuentren un modelo que explique razonablemente bien los viajes entrantes a la escala agregada; pueden utilizar únicamente las regiones presentadas en el ShapeFile
de nombre randmo_1.shp
, utilizada al principio de esta sección, para no estar sujetos a la aleatoriedad de la celda anterior.
A partir de este modelo, ahora sí, utilicen el proceso de la celda anterior para hacer diferentes experimentos y registrar los parámetros más importantes, como $R^2$, los Coeficientes y las Significancias de las variables. Con los resultados de varias repeticiones traten de demostrar que las diferencias son aleatorias (es decir, siguen una Distribución Normal).
Ahora, vamos a trabajar sobre tres agregaciones diferentes de los datos, en la misma escala que las hechas, pero sobre las que no tenemos control. Simplemente, son las unidades que tenemos (de forma similar a las AGEB's, por ejemplo).
Lo primero es leer los nuevos datos:
datos_nuevos = GeoDataFrame.from_file('data/variables_regiones.shp')
datos_nuevos.head()
Como pueden ver, son exactamente igual a los originales, salvo por las columnas nuevas region_1
, region_2
y region_3
. Éstas son, justamente, las nuevas agregaciones de datos sobre las cuales nosotros no hemos tenido control; el resto de las variables son idénticas a las anteriores.
Entonces, realicemos exactamente el mismo proceso, esta vez utilizando las nuevas regiones que nos han sido proporcionadas:
# REGIÓN 1
# Agrupar según la Región 1
r_1 = datos_nuevos.groupby(by = 'region_1').sum()
# Recalcular el Índice de Entropía
intensidad = r_1['comercio'] + r_1['viv'] + r_1['ocio'] + r_1['servicios']
prop_comercio = r_1['comercio'] / intensidad
prop_viv = r_1['viv'] / intensidad
prop_ocio = r_1['ocio'] / intensidad
prop_servicios = r_1['servicios'] / intensidad
entropia = (prop_comercio*np.log(prop_comercio) + prop_viv*np.log(prop_viv) + prop_ocio*np.log(prop_ocio)
+ prop_servicios*np.log(prop_servicios))/np.log(4)
r_1['entropia'] = entropia
# Generar la Regresión Lineal
variables = r_1[['entrada', 'viv', 'entropia']]
vars_norm = (variables - variables.mean()) / variables.std()
model_1 = sm.ols('entrada ~ viv + entropia' , data = vars_norm).fit()
# Visualizar el resultado
model_1.summary()
# REGIÓN 2
# Agrupar según la Región 2
r_2 = datos_nuevos.groupby(by = 'region_2').sum()
# Recalcular el Índice de Entropía
intensidad = r_2['comercio'] + r_2['viv'] + r_2['ocio'] + r_2['servicios']
prop_comercio = r_2['comercio'] / intensidad
prop_viv = r_2['viv'] / intensidad
prop_ocio = r_2['ocio'] / intensidad
prop_servicios = r_2['servicios'] / intensidad
entropia = (prop_comercio*np.log(prop_comercio) + prop_viv*np.log(prop_viv) + prop_ocio*np.log(prop_ocio)
+ prop_servicios*np.log(prop_servicios))/np.log(4)
r_2['entropia'] = entropia
# Generar la Regresión Lineal
variables = r_2[['entrada', 'viv', 'entropia']]
vars_norm = (variables - variables.mean()) / variables.std()
model_2 = sm.ols('entrada ~ viv + entropia' , data = vars_norm).fit()
# Visualizar el resultado
model_2.summary()
Ustedes pueden generar ahora el Tercer Modelo.
La pregunta es, ¿qué es lo que está ocurriendo? ¿Por qué se están obteniendo valores tan diferentes a los que se tenían antes?
Ejercicio Final - Tratar de explicar este fenómeno.