Análisis Exploratorio de Datos con R

En esta sección ilustraremos brevemente algunas técnicas estándar para el análisis exploratorio de datos. Para aquellos que buscan una introducción más detallada sobre estadísticas básicas con R refiéranse a Dalgaard (2002).
Usaremos los datos contenidos en CPS1985 tomados de Berndt (1991). Después de tener disponibles los datos vía data(), podremos tener alguna información a través de la función str(). Todo este análisis fue tomado de Kleiber y Zeileis (2008). Descarga los códigos usados en este post aquí

> data("CPS1985", package="AER")
> str(CPS1985)
'data.frame':   533 obs. of  11 variables:
$ wage      : num  4.95 6.67 4 7.5 13.07 ...
$ education : int  9 12 12 12 13 10 12 16 12 12 ...
$ experience: int  42 1 4 17 9 27 9 11 9 17 ...
$ age       : int  57 19 22 35 28 43 27 33 27 35 ...
$ ethnicity : Factor w/ 3 levels "cauc","hispanic",..: 1 1 1 1 1 1 1 1 1 1 ...
$ region    : Factor w/ 2 levels "south","other": 2 2 2 2 2 1 2 2 2 2 ...
$ gender    : Factor w/ 2 levels "male","female": 2 1 1 1 1 1 1 1 1 1 ...
$ occupation: Factor w/ 6 levels "worker","technical",..: 1 1 1 1 1 1 1 1 1 1 ...
$ sector    : Factor w/ 3 levels "manufacturing",..: 1 1 3 3 3 3 3 1 3 3 ...
$ union     : Factor w/ 2 levels "no","yes": 1 1 1 1 2 1 1 1 1 2 ...
$ married   : Factor w/ 2 levels "no","yes": 2 1 1 2 1 1 1 2 1 2 ...
>

Esta salida revela que CPS1985 es un “data.frame” compuesto por 533 observaciones y 11 variables, incluyendo la variable numérica (continua) wage, las variables numéricas (enteras) education, experience, and age y siete “factores” (variables categóricas, llamadas Factor en R) cada una con 6 categorías (las categorías son llamas niveles (levels) en R).
En vez de utilizar la vista tipo lista que nos proporciona la función str(), es más usual inspeccionar el inicio y el final de la base de datos (data.frame) en su forma natural, es decir, como un arreglo rectangular de valores. Para este objetivo existen funciones apropiadas tales como head() y tail() que nos proporcionan (por defecto) las primeras 6 observaciones y las últimas 6 observaciones de cada variable, respectivamente. Así por ejemplo,
head(CPS1985)
   wage education experience age ethnicity region gender occupation
1  4.95         9         42  57      cauc  other female     worker
2  6.67        12          1  19      cauc  other   male     worker
3  4.00        12          4  22      cauc  other   male     worker
4  7.50        12         17  35      cauc  other   male     worker
5 13.07        13          9  28      cauc  other   male     worker
6  4.45        10         27  43      cauc  south   male     worker
         sector union married
1 manufacturing    no     yes
2 manufacturing    no      no
3         other    no      no
4         other    no     yes
5         other   yes      no
6         other    no      no
>

Por razones de espacio no se presenta el resultado de aplicar tail(CPS1985), pero el lector lo puede ejecutar y verá que la información que proporciona es muy semejante a head(CPS1985), la diferencia es que tail() da las últimas 6 filas como se ha señalado antes.
Otra manera apropiada y rápida de obtener un resumen de la información contenida en la base de datos es a través de la función summary() la cual proporciona un resumen por cada una de las variables.
> summary(CPS1985)
      wage          education       experience         age      
Min.   : 1.000   Min.   : 2.00   Min.   : 0.00   Min.   :18.00 
1st Qu.: 5.250   1st Qu.:12.00   1st Qu.: 8.00   1st Qu.:28.00 
Median : 7.780   Median :12.00   Median :15.00   Median :35.00 
Mean   : 9.031   Mean   :13.03   Mean   :17.82   Mean   :36.84 
3rd Qu.:11.250   3rd Qu.:15.00   3rd Qu.:26.00   3rd Qu.:44.00 
Max.   :44.500   Max.   :18.00   Max.   :55.00   Max.   :64.00 
    ethnicity     region       gender         occupation            sector  
cauc    :440   south:156   male  :289   worker    :155   manufacturing: 98 
hispanic: 26   other:377   female:244   technical :105   construction : 24 
other   : 67                            services  : 83   other        :411 
                                         office    : 97                     
                                         sales     : 38                     
                                         management: 55                     
union     married 
no :437   no :184 
yes: 96   yes:349  
    
Dado que en lo sucesivo de esto post se utilizará repetidamente la base CSP1985, trataremos de evitar usar comandos muy extensos como CSP1985$education para ello separaremos cada variable de la base de datos y así podremos acceder a ella directamente por su nombre sin necesidad de anteponer el nombre de la base donde están contenidas, para lograr eso haremos uso de la función attach(). Además para evitar escribir muchas letras, renombraremos y abreviaremos los nombres de dos niveles (categorías) de la variable occupation, cambiaremos “techcnical” por “techn” y “management” por mgmt.
> levels(CPS1985$occupation)[c(2,6)]<-c("techn", "mgmt")
> attach(CPS1985)



Ahora las variables son accesibles por sus nombres.


Es hora del análisis, procederemos con él ilustrando cómo se hace una análisis exploratorio considerando una sola variable, luego pares de variables, haciendo la distinción entre variables numéricas, factores (categóricas) y combinaciones de ambas. Empezamos con el caso más simple, considerando una única variable.

Sólo una  variable numérica

Empezaremos dando una mirada a la distribución de los salarios de la muestra, esto es la variable wage
> summary(wage)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.
  1.000   5.250   7.780   9.031  11.250  44.500



La función summary() proporciona un resumen de seis números: el valor mínimo, el primer cuartil, el segundo cuartil (=mediana), el tercer cuartil, el valor máximo y el valor medio de la distribución. La media y la mediana también se pudieron haber obtenido de la siguiente manera
> mean(wage) 
[1] 9.031426
> median(wage)
[1] 7.78



y la función fivenum() calcula un resumen de las cinco medidas de posición no central listados anteriormente. En tanto que, min() y max() habrían proporcionado el mínimo y el máximo valor de la distribución. Los cuartiles se podrían haber obtenido usando quantile().

Para las medidas de dispersión, existen las funciones
> var(wage)
[1] 26.43096
> sd(wage)
[1] 5.141105



que nos devuelven el valor de la varianza y el de la desviación típica (desviación estándar según guste llamarla).



Los resúmenes gráficos también son muy útiles. Para variables numéricas como el caso de wage, las visualizaciones de densidad (vía histogramas o “kernel smoothing”) y los diagramas de caja son adecuados. Los diagramas de caja se considerarán cuando se nos refiramos a análisis de dos variables.  La Figura 1, obtenida vía


par(mfcol=c(1,2))Figura 1
hist(wage, freq=F)
hist(log(wage), freq=F)
lines(density(log(wage)), col=4)

muestra las densidades de wage y su logaritmo (esto es, el área bajo la curva es igual a 1, resultando del hecho de freq=FALSE; de otra manera las frecuencias absolutas habrían sido dibujadas). En el panel derecho de la Figura 1 se ha añadido al histograma la densidad kernel  estimada a partir de la función density(). Claramente, la distribución de los logaritmos es menos sesgada que la de los datos originales (datos brutos).  Note que density() sólo calcula las coordenadas de la densidad pero no la grafica, por eso esta estimación es agregada usando la función lines().

Figura 1. Histogramas de wages (izq.)  y de su logaritmo
con densidad superpuesta (derecha)

Sólo una variable categórica

Para datos categóricos, no tiene mucho sentido calcular la media ni la varianza; en su lugar, lo que necesitamos es una tabla que nos indique las frecuencias con las cuales las categorías ocurren. Si a R se le dice que cierta variable es categórica (haciéndola un “factor”), él automáticamente escogerá el resumen adecuado:
> summary(occupation)
  worker    techn services   office    sales     mgmt
     155      105       83       97       38       55



Esto también pudo haber sido calculado a través de table(occupation). Si en lugar de las frecuencias absolutas, lo que se desea son las frecuencias relativas, entonces existe la función prop.table() que lo hace.

Figura 2
> tab<-table(occupation)
> prop.table(tab)
occupation
    worker      techn   services     office      sales       mgmt
0.29080675 0.19699812 0.15572233 0.18198874 0.07129456 0.10318949

Las variables categóricas con comúnmente visualizadas mediante diagramas de barras, los gráficos de pastel también son útiles. Ejemplo,
> barplot(tab)
> pie(tab)


Figura 2. Diagrama de barras y de pastel de occupation


Note cómo ambas funciones utilizan las frecuencias como input. Utilizando la función plot(occupation)  se logra lo mismo que se logró con barplot(table(occupation)), estos procedimientos son equivalentes, pero usando plot() se va directamente al gráfico no hay cálculos intermedios como los hay si se utiliza barplot() en la que primero se debe calcular la tabla de frecuencias.

Dos variables categóricas

La relación entre dos variables categóricas es frecuentemente resumida en una tabla de contingencia. Estas tablas pueden ser creadas ya sea con xtabs() una función que requiere de una fórmula de interface o con table(), que es una función que toma arbitrariamente un número de variables para la tabulación cruzada . Consideremos los factores (variables categóricas) occupation y gender para ilustrar:Figura 3
> xtabs(~ gender + occupation, data=CPS1985)
        occupation
gender   worker techn services office sales mgmt
  male      126    53       34     21    21   34
  female     29    52       49     76    17   21

Lo cual pudo haber sido creado de forma equivalente con table(gender, occupation). Una simple visualización de esto es a través de un “mosaic plot” (Hartigan y Kleiner 1981; Friendly 1994), el cual es visto como una generalización de los gráficos de columnas apiladas. El gráfico dado en la Figura 3 (también conocido como “spine plot”, que es una variante de la presentación estándar de la forma estilo mosaico), se obtuvo vía


Figura 3. Mosaic plot (spine plot) de gender vs occupation


> plot(gender~occupation, data=CPS1985)

La Figura 3 muestra que la proporción de hombres y mujeres cambia considerablemente entre las categorías de ocupación (niveles de occupation). Además de las partes sombreadas que nos muestran la distribución condicional del género (gender) dada la ocupación (occupation), la anchura de las barras ofrecen la distribución marginal de la ocupación, indicando que hay comparativamente muchas personas en la categoría “workers”  y menos en “sales”, es decir más obreros que vendedores.


Dos variables numéricas

Ejemplificaremos el análisis exploratorio de la relación entre dos variables numéricas utilizando las variables wage y education.Figura 4
Una medida de relación entre dos variables numéricas es el coeficiente de correlación implementado en la función cor(). Sin embargo, el coeficiente de correlación estándar de Pearson no es muy significativo cuando estamos ante variables con un pronunciado sesgo positivo como es el caso de wage, de manera que calcularemos una versión no paramétrica del coeficiente de correlación, usaremos la correlación de Spearman, la cual está disponible en la función cor() como una opción.
> cor(log(wage), education)
[1] 0.3790093
> cor(log(wage), education, method="spearman")
[1] 0.3797895



Figura 4. Diagrama de dispersión de wage (en logs) vs education


Ambas medidas son virtualmente idénticas e indican sólo una modesta correlación entre las variables, veamos el correspondiente diagrama de dispersión en la Figura 4.
> plot(log(wage)~ education)

Una variable numérica y una variable categórica

Es común tener tanto variables numéricas como categóricas en un data frame. Por ejemplo, en nuestro caso tenemos wage y gender y podría haber algún interés en saber la distribución del salario dado el género. Una función adecuada para resumir este tipo de datos combinados es tapply(). Esta función aplica a la variable numérica que es su primer argumento una clasificación según la variable categórica que es su segundo argumento y a la vez aplica la respectiva función que hayamos establecido, esto es el tercer argumento de la función tapply(). Así por ejemplo, es posible obtener la media de los salarios condicionado al género de la siguiente manera

> tapply(log(wage), gender, mean)
    male   female
2.165286 1.935287



Usando comandos similares pueden obtenerse más estadísticos descriptivos o incluso se puede obtener un resumen completo, basta con sustituir summary en el lugar de mean y se obtendrá


> tapply(log(wage), gender, summary)
$male
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.
  0.000   1.792   2.189   2.165   2.565   3.269

$female
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.
0.5596  1.5510  1.9230  1.9350  2.3030  3.7950



Adecuadas salidas gráficas para estos datos tales como diagramas de cajas y diagrama cuartil-cuartil (quantile-quantile plot, qq-plot) se presentan en la Figura 5.
Figura 5
Figura 5. Diagrama de Cajas y QQ plot de wage estratificado por gender

Los comandos plot(y~x) y boxplot(y~x) proporcionan el mismo resultado si x es un factor (variable categórica), así pues
plot(log(wage)~gender)


proporcionará la parte izquierda de la Figura 5. Este muestra que las distribuciones son bastante similares en su forma pero con la salvedad que los hombres disfrutan de una ventaja substancial, especialmente los del rango medio. Este último aspecto es corroborado por el QQ-plot que está a la derecha de la Figura 5 el cual resulta de ejecutar la siguiente secuencia de comandos
mwage <- subset(CPS1985, gender=="male")$wage
fwage <- subset(CPS1985, gender=="female")$wage

qqplot(mwage, fwage, xlim=range(wage), ylim=range(wage),
    xaxs="i", yaxs="i", xlab="male", ylab="female")
abline(0,1)



donde la mayoría de puntos están debajo de la línea diagonal (la cual corresponde a una idéntica distribución en ambas muestras). Este gráfico nos dice que para la mayoría de cuantiles, el salario de los hombres es mayor que el de las mujeres.

Acabamos este post volviendo a unir todas las variables en una sola base de datos con
detach(CPS1985)


Referencias

Dalgaard P (2002). Introductory Statistics with R. Springer-Verlang, New York.
Friendly M (1994). Mosaic Displays for Multi-Way Contingency Tables. Journal of the American Statistical Association, 89, 190-200.
Hartigan J A, Kleiner B (1981). Mosaics for Contingency Tables. In W" Eddy (ed.), “Computer Science and Statistics: Proceedings of the 13th Symposium on the Interface”, pp. 268-273. Springer-Verlang, New York.
Kleiber y Zeileis (2008). Applied Econometrics with R. Springer. New York.

Jilber Urbina.

No hay comentarios:

Publicar un comentario