Table of contents
Open Table of contents
- Visualización
- Análisis Exploratorio de Datos (Estadística Descriptiva)
- Ejemplo: Amortización de la vivienda en Colombia.
- Ejercicio, Edades en Cundinamarca
- Correlación (DSS) (PSDS) (OIS)
- Paradoja de Simpson o Falacia de Causa Simple (DSS)
- Correlación y Causación (DSS)
- Hipótesis e Inferencias (DSS)
- A/B (PSDS)
- Statistical Hypothesis testing (DSS) (PSDS)
- Confidence Intervals (DSS)
- p-Hcking (DSS)
- Inferencia Bayesiana (DSS)
- ANOVA (PSDS)
- Inferencia
- Regresión
Visualización
Los siguientes temas podrían incluirse en Análisis exploratorio, si no se han incluid ya explícitamente en Visualización
- Scatterplots. PSDS, pg.34
- Histogramas. DSPP, pg. 89
Análisis Exploratorio de Datos (Estadística Descriptiva)
Con la creciente digitalización de muchas actividades humanas cada vez es más sencillo acceder a variadas fuentes de datos. Idealmente antes de recopilar los datos hay un proceso de diseño experimental, en el que se definen unos objetivos y se plantean unas hipótesis; aunque no siempre es el caso.
Una vez tenemos los datos es importante describirlos o caracterizarlos. Aquí entra el Análisis Exploratorio de datos. Éste método es una revisión de la estructura de los datos, y su fortaleza está en usar gráficos y visualizaciones para ese proceso de obtener información que pueda usarse en formular o refutar validar las hipótesis relativas a las variables bajo estudio; como también validar las suposiciones que tengamos sobre ellas.
Aquí seguimos el libro de Chen1, que propone las siguientes fases.
Fase | Preguntas comunes |
---|---|
Coherencia conceptual de los datos | ¿Cómo se recogieron los datos? |
¿Que fuentes potenciales de error hay en los datos? | |
¿Qué significa cada variable? | |
¿Que unidades de medida tiene la variable y tiene sentido para el análisis que se plantea hacer? | |
Preprocesamiento | ¿Estamos leyendo/interpretando los tipos de datos de manera adecuada? |
¿Que manipulaciones son necesarias para asignar/definir las variables en la forma requerida (por ejemplo, como vector, como matriz, como conjunto de datos) | |
¿Es necesario agregar los datos? | |
Calidad de la Señal | ¿es posible determinar la tendencia central? |
¿A que típo de distribución se asemeja más? | |
¿Hay una dependencia temporal o espacial en los datos? | |
Identificación de datos problemáticos | ¿las gráficas muestran datos posiblemente errados? |
¿Al graficar como serie, hay datos que tengan valores muy diferentes a los demás? | |
¿Hay datos faltantes? | |
Identificación de variables importantes | ¿Hay variables correlacionadas? |
¿Se puede hacer una modificación para mejorar la correlación? |
Tipos de datos faltantes
Según Chen et al., existen tres tipos de datos faltantes:
-
Datos faltantes distribuidos completamente al azar. Los datos faltantes de una variable no están relacionados con las demás variables del conjunto de datos. Usualmente esto no afecta el análisis.
-
Datos faltantes distribuidos al azar. Los datos faltantes dependen de otra variable. Por ejemplo, quienes no responden una pregunta de ingreso tienden a tener un bajo nivel educativo. Aquí normalmente es a lugar hacer un ajuste.
-
Datos faltantes no distribuidos al azar. Los datos faltantes se correlacionan con un concepto medido. Por ejemplo, las personas pueden no responder a la pregunta sobre el ingreso porque tienen altos ingresos. En estos casos se requiere conocer profundamente la teoría relacionada con la encuesta para poder analizar.
Además proponemos la siguiente categoría:
- Datos faltantes no necesarios. Cuando no se registra el valor porque la definición de la variable o de otra variable implica que el dato mismo no tiene sentido. Por ejemplo, a un bebé no se le pregunta si ha tenido hijos.
Coeficiente de Sesgo
En una distribución simétrica habrá en términos generales el mismo número de valores por encima o por debajo del promedio. Cuando hay un desbalance entre los valores arriba y abajo del promedio se habla de un sesgo.
-
Los datos de una distribución tienen un sesgo positivo cuando existen unos pocos valores que están muy alejados por encima del promedio (y la distribución no hay valores muy alejados por debajo del promedio)
-
Los datos de una distribución tienen un sesgo negativo cuando existen unos pocos valores que están muy alejados por debamo del promedio (y la distribución no hay valores muy alejados por encima del promedio)
Matemáticamente el valor de sesgo se calcula mediante:
Como la expresión está elevada al cubo, los valores negativos ( menores que al elevarse al cubo mantienen su signo y si la diferencia es grande estamos sumando un valor negativo muy grande a la suma. De la misma forma si es mucho más grande que , la resta da un valor positivo, que al elevarse al cubo suma un valor muy grande a la suma.
Ejemplo: Amortización de la vivienda en Colombia.
El Departamento Nacional de Estadística de Colombia (Dane) publica los microdatos de diferentes proceso estadísticos que lleva a cabo. Tenemos por ejemplo la encuesta nacional de calidad de vida, que busca caracterizar dimensiones del bienestar, como la salud, educación, actividades laborales y tenencia de bienes del hogar2.
Enfoquémonos en la variable P5100, ¿Cuánto pagan mensualmente por cuota de amortización?
. En la descripción del análisis
estadístico3 se explica la forma de recolección de datos de la
encuesta.
Revisemos la fase de coherencia conceptual:
Fase | Preguntas comunes | Análisis |
---|---|---|
Coherencia conceptual de los datos | ¿Cómo se recogieron los datos? | Se describe en la sección ‘muestreo’ de la descripción de los datos3. |
¿Que fuentes potenciales de error hay en los datos? | En este caso puede haber datos faltantes, errores de unidades (ejemplo, registrar 1 en lugar de 1000000 para un millón), o errores al registrar con texto en lugar de valores numéricos. | |
¿Qué significa cada variable? | Se define como “el gasto en que incurre el hogar para cubrir el crédito de vivienda que ha adquirido”. | |
¿Que unidades de medida tiene la variable y tiene sentido para el análisis que se plantea hacer? | La descripción de la variable indica ”$”, es necesario confirmarlo mediante el análisis exploratorio. |
Descargamos los datos de la página del Dane, en este caso el archivo de Tenencia y financiación de la vivienda que ocupa, de la página del dane 4. Descomprimimos los datos desde el sistema operativo.
Comenzamos con el preprocesamiento. Inicialmente incluímos las librerías:
# coding: utf-8
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
Cerramos las ventanas que puedan estar abiertas:
plt.close('all')
plt.ion()
En Python procedemos a cargar los datos
datos = pd.read_csv('Tenencia y financiación de la vivienda que ocupa el hogar.CSV')
Nos hacemos la pregunta:
Fase | Preguntas comunes | Análisis |
---|---|---|
Preprocesamiento | ¿Estamos leyendo/interpretando los tipos de datos de manera adecuada? | Para responder esta pregunta, imprimimos las variables. Como la información está guardada en el dataframe datos , esto se hace con la expresión: datos.columns . |
La salida de éste comando es el texto:
Index(['DIRECTORIO;SECUENCIA_ENCUESTA;SECUENCIA_P;ORDEN;FEX_C;P5095;P5100;P3197;P5120;P8692;P8692S1A1;P8692S2;P5610;P5610S1;P8693;P5110;P5130;P5140;P3006;P5650;P5160;P5160S1;P5160S1A1;P5160S2;P5160S2A1'], dtype='object')
Notese que se trata de una lista (se define porque abre el paréntesis
cuadrado [
y cierra con ]
). Los elementos de las listas se separan
por comas, pero aquí tenemos punto y coma. Esto indica que
probablemente la primera línea, que debía tener varias variables, se
interpretó como una sóla variable.
Otra forma de verlo es imprimir la variable shape
del DataFrame:
print(datos.shape)
Se obtiene (86405, 1)
, es decir, este DataFrame tiene 86405
registros, para una única variable. Otra forma de confirmar esta
situación errónea es usar la variable head del dataframe:
print(datos.head)
5:
bound method NDFrame.head of DIRECTORIO;SECUENCIA_ENCUESTA;SECUENCIA_P;ORDEN;FEX_C;P5095;P5100;P3197;P5120;P8692;P8692S1A1;P8692S2;P5610;P5610S1;P8693;P5110;P5130;P5140;P3006;P5650;P5160;P5160S1;P5160S1A1;P5160S2;P5160S2A1
0 7910114;1;1;1;282.37094522;3;;;;;;;;;;;;400000...
1 7910115;1;1;1;3.0542169534;6;;;;;;;;;;;200000;...
2 7910119;1;1;1;31.288476991;4;;;;;;;;;;;250000;...
3 7910120;1;1;1;73.57774897;1;;2;2;;;;0;;0;12000...
Vemos que los datos están separados por ;
, entonces se deben indicar
que éste es el separador. Es decir:
datos = pd.read_csv('Tenencia y financiación de la vivienda que ocupa el hogar.CSV',sep=';')
Volvemos a revisar que se haya cargado bien, con datos.columns
, obteniendo:
print(datos.columns)
Index(['DIRECTORIO', 'SECUENCIA_ENCUESTA', 'SECUENCIA_P', 'ORDEN', 'FEX_C',
'P5095', 'P5100', 'P3197', 'P5120', 'P8692', 'P8692S1A1', 'P8692S2',
'P5610', 'P5610S1', 'P8693', 'P5110', 'P5130', 'P5140', 'P3006',
'P5650', 'P5160', 'P5160S1', 'P5160S1A1', 'P5160S2', 'P5160S2A1'],
dtype='object')
Esto es una lista, separada por comas, donde hay 25 datos,
correspondientes a 25 variables. Esto también se ve de la variable
datos.shape
, que ahora es la pareja: (86405, 25), es decir 86405
registros de 25 variables.
Explorando datos faltantes (DSPP)
Los datos que nos interesan corresponden a la variable P5100
,
entonces para estar seguros de que tenemos los datos de esa variable,
procedemos a imprimir los valores únicos. En Python se obtiene con:
datos.P5100.unique()
. Aquí tenemos un vector de 271 elementos. El
primer número de ese vector es nan
, o ‘Not A Number’, lo que
refuerza nuestra hipótesis de que en los datos podemos tener valores
faltantes.
Para construir un vector indique la posición de los valores faltantes,
usamos: datos.P5100.isnull()
. La suma de éste vector nos dará el
número de datos faltantes: sum(datos.P5100.isnull())
, en este caso
84745. La proporción de datos faltantes sería:
print(sum(datos.P5100.isnull())/len(datos.P5100))
Esto da una fracción de 0.98 del total de datos.
Revisando el diccionario de datos, existe otra variable relacionada.
Pregunta | Código | Descripción | Opciones |
---|---|---|---|
¿La vivienda ocupada por este hogar es? | P5095 | Con esta pregunta se quiere conocer la forma de tenencia de la vivienda que ocupa el hogar | 1. Propia, totalmente pagada 2. Propia, la están pagando 3. En arriendo o subarriendo 4. Con permiso del propietario, sin pago alguno (usufructuario) 5. Posesión sin título (ocupante de hecho) 6. Propiedad colectiva |
Entonces tenemos que los únicos registros donde debería haber un valor
de pago por amortización son quienes están pagando. O al contrario,
los que no deberían tener registro del valor son los que no están
pagando. Estos últimos registros no tienen un número 2 en la variable
P5095. Es decir, son los registros para los que: datos.P5095!=2
. La
suma de estos valores se construye con: sum)datos.P5095!=2
. Lo que
también nos dá como resultado 84745. Es decir, los valores faltantes
de la variable P5100 son faltantes no necesarios.
Continuamos el preprocesamiento:
Fase | Preguntas comunes | Análisis |
---|---|---|
Preprocesamiento | ¿Que manipulaciones son necesarias para asignar/definir las variables en la forma requerida (por ejemplo, como vector, como matriz, como conjunto de datos) | Los datos están cargados en un DataFrame. Requerimos filtrar los datos faltantes. Para ello podemos definir una variable que corresponda a los valores no nulos. |
El comando es:
pagoamortizacion = datos.P5100[~datos.P5100.isnull()]
Estadísticos de centro
Continuamos con el preprocesamiento:
Fase | Preguntas comunes | Análisis |
---|---|---|
Preprocesamiento | ¿Es necesario agregar los datos? | En este caso tiene sentido agregar, porque esperamos que la variable tenga una dispersión y justamente queremos saber cómo se distribuye. Para esto podemos calcular estadísticos de centro y variabilidad y construir un histograma. |
En Python los estadísticos de centro se hallan con la función describe
:
print(pagoamortizacion.describe())
Y se obtiene:
count 1.660000e+03
mean 8.007266e+05
std 8.576620e+05
min 9.900000e+01
25% 3.000000e+05
50% 5.500000e+05
75% 1.000000e+06
max 9.000000e+06
Name: P5100, dtype: float64
Luego tenemos 1660 datos, con un promedio de 800726.6, un mínimo de 99 y un máximo de 9000000. Estos valores refuerzan la hipótesis de que la unidad de la variable son los pesos. Podemos planear entonces construir un histograma que tenga divisiones cada 500 mil pesos, desde 0 hasta 9 millones.
binamort = np.linspace(0,9e6,19)
Construimos el histograma normalizado:
plt.hist(pagoamortizacion,edgecolor='w',bins=binamort,density=True,label='histograma normalizado')
El análisis no está completo si no se incluyen las unidades de medida, y los nombres de las clases. Lo hacemos así:
binamortmillones = binamort/1e6 # para usar en el texto
xbinstxt = [str(binamortmillones[i])+' a '+str(binamortmillones[i+1]) for i in range(len(binamortmillones)-1)] # Genera el texto de las etiquetas
plt.subplots_adjust(bottom=0.2,left=0.2) # mejora el espacio abajo y la izquierda
plt.ticklabel_format(style = 'plain') # simplifica las unidades
plt.xlabel("Cuota (millones)") # texto en el eje x
plt.title("Pagos de amortización") # título de la gráfica
xbins = [(binamort[i]+binamort[i+1])/2 for i in range(len(binamort)-1)] # posición del texto de las clases
ax.set_xticks(xbins,xbinstxt,rotation=45) # texto de las clases
plt.legend()
Adicionalmente se puede incluir una aproximación continua a la
distribución. Una forma de hacerlo es usar la librería seaborn de
Python6. Chen et al. explican cómo hacerlo en R
, en la página 91.
sns.kdeplot(data=pagoamortizacion,label="densidad",fill=True, alpha=0.6)
Adicionalmente se puede exportar la gráfica:
plt.savefig("amortizacion_ecv_23.png")
Con esto se obtiene la siguiente gráfica:
Continuamos con el análisis.
Fase | Preguntas comunes | Análisis |
---|---|---|
Calidad de la Señal | ¿es posible determinar la tendencia central? | Calculamos el valor del promedio en alrededor de 800 mil pesos, y la mediana en 550 mil pesos como medidas de tendencia central |
¿A que típo de distribución se asemeja más? | Es una distribución unimodal, asimétrica, con cola a la izquierda. | |
¿Hay una dependencia temporal o espacial en los datos? | No tenemos información temporal en este conjunto de datos. La encuesta es en un momento del tiempo, luego la dependencia temporal podría revisarse comparando con otras versiones de la encuesta | |
Identificación de datos problemáticos | ¿las gráficas muestran datos posiblemente errados? | No encontramos datos extraños. |
¿Hay datos faltantes? | Si, ya se discutió anteriormente. | |
¿Al graficar como serie, hay datos que tengan valores muy diferentes a los demás? | Construimos una gráfica de dispersión para los datos. En ésta gráfica no se ven valores atípicos. |
El diagrama de dispersión se genera con el siguiente código:
plt.figure()
plt.plot(pagoamortizacion,'.')
plt.title('valores amortización')
plt.xlabel('consecutivo')
plt.ticklabel_format(style = 'plain')
plt.savefig("amortizacion_consecutivo_ecv_23.png")
Obtenemos la siguiente gráfica:
Aquí vemos que los puntos se distribuyen alrededor de el valor 500 mil, reforzando lo que habíamos encontrado anteriormente. No hay datos especialmente extraños.
Skewed variables (DSPP)
El sesgo se calcula en Pandas usando la función skew
del
DataFrame. En este caso tenemos:
print(pagoamortizacion.skew())
Obtenemos un valor de 3.705296, lo que corresponde a un sesgo positivo. Esto era de esperarse por la forma de la distribución que habíamos visto anteriormente.
Ejercicio, Edades en Cundinamarca
Utilizando los datos del Censo Nacional de Población y Vivienda 2018, lleve a cabo los análisis similares a los que hicimos en ésta sección para la variable de Edades. Encuentre los valores faltantes. El histograma debe ser similar al siguiente:
Construya también el diagrama de dispersión y analícelo.
Correlación (DSS) (PSDS) (OIS)
La correlación es una medida sobre que tanto están relacionadas dos variables. Toma valores numéricos en el intervalo . Por ejemplo, el coeficiente de correlación de Pearson se calcula multiplicando las desviaciones de la media de la primera variable con las desviaciones de la media de la segunda variable y dividiendo entre el producto de las desviaciones estandar y los grados de libertad. Llamemos las variables y . El coeficiente de Pearson es:
Correlación entre diferentes variables de la ECV
En el texto de Chen1 se incluyen dos preguntas relacionadas con la correlación entre las variables.
Para llevar a cabo el análisis, construimos un DataFrame que incluya
variables de las categorías educación
y salud
de la encuesta
calidad de vida. La fuente de datos está en
https://microdatos.dane.gov.co/index.php/catalog/827/get-microdata.
Se cargan los datos:
educacion = pd.read_csv('Educación.CSV',sep=';',usecols=['DIRECTORIO','SECUENCIA_P','SECUENCIA_ENCUESTA','P8587','P6216','P6167'])
salud = pd.read_csv('Salud_ajustada/Salud.CSV',sep=';',usecols=['DIRECTORIO','SECUENCIA_P','SECUENCIA_ENCUESTA','P6181','P6127'])
Aquí es necesario hacer un análisis cuantitativo de las variables de
cada DataFrame. La variable P6181
es ‘la calidad de servicio de las
EPS’, en escala desde 1: ‘muy buena’ hasta 5 ‘muy mala’ y 5 ‘no
sabe’. La variable P6127
es ‘el estado de salud’, en escala desde 1
‘Muy Bueno’ hasta 4 ‘Malo’.
print(salud.describe())
DIRECTORIO SECUENCIA_ENCUESTA SECUENCIA_P P6181 P6127
count 2.402120e+05 240212.000000 240212.000000 230206.000000 240212.000000
mean 8.031243e+06 2.296455 1.004138 2.256457 1.999546
std 9.681928e+04 1.404147 0.071554 1.081347 0.560144
min 7.910114e+06 1.000000 1.000000 1.000000 1.000000
25% 7.948281e+06 1.000000 1.000000 2.000000 2.000000
50% 7.993168e+06 2.000000 1.000000 2.000000 2.000000
75% 8.162668e+06 3.000000 1.000000 2.000000 2.000000
max 8.201927e+06 24.000000 6.000000 9.000000 4.000000
Aquí encontramos una inconsistencia en la variable P6181
, porque el
resumen indica que el valor máximo de la variable es 5, pero aparece
registrado un valor de 9. En este caso podemos hacer un filtro para
remover éstos valores. Primero generamos una nueva variable y luego
procedemos a remover la columna.
salud['P6181f'] = salud.P6181[salud.P6181!=9]
salud = salud.drop(columns=['P6181'])
Queda como tarea a quien está leyendo este texto el hacer un análisis descriptivo siguiendo las etapas que están anteriormente para describir las variables del dataframe de salud y de educación que hemos incluido.
Construimos un DataFrame con las varialbes de ambos DataFrames:
df_es_i = pd.merge(left=educacion,right=salud,how='inner',left_on=["DIRECTORIO",'SECUENCIA_P',"SECUENCIA_ENCUESTA"], right_on=["DIRECTORIO",'SECUENCIA_P',"SECUENCIA_ENCUESTA"])
Las tres primeras variables corresponden a la identificación de los registros, por lo tanto no es necesario incluirlas en el análisis de correlación.
dfsinetiquetas = df.drop(columns=['DIRECTORIO','SECUENCIA_ENCUESTA', 'SECUENCIA_P'])
En Pandas se incluye la función corr
, que permite calcular
diferentes tipos de correlación. Para construir la gráfica de la
correlación, usamos las siguientes instrucciones:
plt.figure()
plt.title("Correlación")
sns.heatmap(dfsinetiquetas.corr(), vmin=-1, vmax=1,cmap=sns.diverging_palette(20, 220, as_cmap=True))
plt.savefig("correlacion.png")
Lo que nos genera la siguiente gráfica:
El texto de Chen1 propone dos preguntas sobre la correlación. La primera:
Fase | Preguntas comunes | Análisis |
---|---|---|
Identificación de variables importantes | ¿Hay variables correlacionadas? | Se encuentra una correlación positiva entre la variable P6127, “el estado de salud en general” y P6181, “la calidad del servicio de la EPS”. |
Fase | Preguntas comunes | Análisis |
---|---|---|
Identificación de variables importantes | ¿Se puede hacer una modificación para mejorar la correlación? |
Cruzar variables
los diferentes censos. ¿qué dice un análisis exploratorio de las variables ‘Edad’ y ‘Lugar de Residencia hace 5 años’ de la categoría personas?
Paradoja de Simpson o Falacia de Causa Simple (DSS)
Es el fenómeno en el que las correlaciones pueden llevar a conclusiones erróneas, cuando no se tiene en cuenta las llamadas “variables de confusión”.
TODO : DSS tiene un ejemplo en el que se calcula el promedio de una variable (# amigos), y se ordena mediante otra (Costa: Este u Oeste), ocultando una tercera, Degree (PhD o No PhD). Incluir algo similar.
Correlación y Causación (DSS)
TODO: DSS explica con un ejemplo, se podría incluir otro
Hipótesis e Inferencias (DSS)
A/B (PSDS)
Statistical Hypothesis testing (DSS) (PSDS)
Confidence Intervals (DSS)
p-Hcking (DSS)
Inferencia Bayesiana (DSS)
ANOVA (PSDS)
Inferencia
Regresión
Regresión Lineal Simple
Regresión Múltiple
Regresión Cuadrática
Regresión Discontinua (evaluación de impacto)
Bibliografía
- R for Data Science. https://r4ds.hadley.nz/
- Representing text as data. https://uclspp.github.io/PUBL0099/seminars/seminar1.html
- Statistical Inference via Data Science. https://moderndive.com/v2/sampling.html
- Data Science for Public Policy. Chen, Rubin, Cornwall.
- Practical Statistics for Data Science. Bruce, Bruce, Gedeck.
- Data Science from Scratch. Grus.
- Microdatos DANE, Censo Nacional de Población y Vivienda 2018, Módulo Personas, Región Cundinamarca. https://microdatos.dane.gov.co/index.php/catalog/643/get-microdata
- Microdatos DANE, Censo Nacional de Población y Vivienda 2018, Diccionario de Datos. https://microdatos.dane.gov.co/index.php/catalog/643/data-dictionary/F11?file_name=PERSONAS
- Dir Datos
/home/gavox/drive/02_Docencia/15_ESAP/06_2024_s1/17_map_mcpi/03_TALLERES/TALLER_1_2024_MCPI/03_YUDY
- https://python-graph-gallery.com/density-plot/
- OpenIntro Statistics. Fourth Edition. David Diez
Footnotes
-
Dane, https://microdatos.dane.gov.co/index.php/catalog/827 ↩
-
https://microdatos.dane.gov.co/index.php/catalog/827/study-description ↩ ↩2
-
https://microdatos.dane.gov.co/index.php/catalog/827/get-microdata ↩
-
También se puede revisar usando el comando
head
de la terminal, en entornos Linux o MacOS X. ↩