Capítulo 1 Capítulo 1: Exploración de los datos

Cuando abordamos el estudio de un conjunto de datos, antes de introducirnos en cuestiones más detalladas, es necesario hacer una exploración inicial de los mismos. Así podemos tener una idea más clara de las características principales de los datos que hemos recogido, y de las posibles asociaciones.

En primer lugar, daremos unas ideas sobre la manera de presentar ordenadamente y resumir variables consideradas aisladamente de las demás, para después explorar conjuntamente grupos de variables.

1.1 Datos Univariantes

Los métodos para visualizar y resumir los datos dependen de sus tipos, que básicamente diferenciamos en dos: categóricos y numéricos.

Los datos categóricos (o factores) son aquellos que registran categorías o cualidades. Si descargamos la base de datos centroSalud-transversal.sav, ejemplos de variables categóricas son el sexo, el estado civil y el nivel de estudios. Dentro de las categóricas podemos a su vez distinguir entre variable nominal y ordinal. En esta última hay un orden entre las distintas categorías como se aprecia en la la variable nivel de estudios y tabaqismo:

df=read_sav("datos/centroSalud-transversal.sav", user_na=FALSE) %>% haven::as_factor()
df %>% head() %>% select(sexo:peso) %>% knitr::kable(booktabs=T)
sexo nivelest tabaco estcivil laboro hijos edad peso
Mujer Sin estudios Ex fumador (9-) años Separado Ama de casa 2 67 72
Hombre Bachillerato No fuma Casado/pareja Jubilado 1 56 150
Hombre Sabe leer y escribir NA Viudo Jubilado 0 81 71
Mujer Sin estudios No fuma Casado/pareja Ama de casa 2 74 85
Hombre Superiores Ex fumador (9-) años Casado/pareja Trabaja 3 53 102
Mujer Sin estudios Ex fumador (9-) años Viudo Jubilado 1 79 98

Siguiendo con la misma base de datos de pacientes, si recogemos, el peso de una persona es una cantidad numérica. En particular continua (los valores dentro de cualquier intervalo son posibles); Esto no ocurre cuando recogemos el número de hijos; Esta variable es discreta.

1.1.1 Datos categóricos

Los datos categóricos los examinamos bien con tablas de frecuencias o con representaciones gráficas como diagramas de barras o de sectores.

1.1.1.1 Frecuencias y porcentajes

Las frecuencias pueden obtenerse en términos absolutos (frecuencias absolutas), mostrando las repeticiones de cada categoría, o bien en términos relativos (porcentajes), mostrando los participación de cada categoría en relación con el total. Las frecuencias absolutas se utilizan con muestras de tamaño pequeño, y las relativas tienen más sentido con muestras de tamaño grande.

tabla=KreateTableOne(vars=c("sexo","laboro", "nivelest", "tabaco",  "diabm"),data = df) 
tabla  %>% knitr::kable()
Overall
n 536
sexo = Mujer (%) 318 (59.3)
laboro (%)
Trabaja 97 (18.3)
Parado 16 ( 3.0)
Jubilado 254 (47.8)
Ama de casa 164 (30.9)
nivelest (%)
Sin estudios 93 (17.5)
Sabe leer y escribir 150 (28.3)
Primarios 188 (35.5)
Bachillerato 53 (10.0)
Superiores 46 ( 8.7)
tabaco (%)
No fuma 133 (25.6)
Ex fumador (10+) años 32 ( 6.2)
Ex fumador (9-) años 272 (52.3)
Fumador 83 (16.0)
diabm = No (%) 369 (69.4)

Si las variables son categóricas ordinales (o numéricas) pueden sernos de interés los porcentajes acumulados. Nos indican para cada valor de la variable, en qué porcentaje de ocasiones se presentó un valor inferior o igual.

1.1.1.2 Diagrama de barras

El diagrama de barras se representa asignándole a cada modalidad de la variable una barra de una altura proporcional a su frecuencia absoluta o a su porcentaje. En ambos casos el gráfico es el mismo, sólo se modifica la escala.

grid.arrange(sjp.frq(df$sexo),  sjp.frq(df$laboro) , sjp.frq(df$nivelest), sjp.frq(df$diabm),ncol=2)

1.1.1.3 Diagramas de sectores

En este diagrama se le asigna a cada valor un sector cuyo ángulo sea proporcional a su frecuencia. Se suele utilizar en datos categóricos nominales y no tanto en los ordinales (es menos clara de interpretar).

grid.arrange(
ggplot(df, aes(x = factor(1), fill = sexo)) + geom_bar(width = 1) + coord_polar(theta = "y") + theme_void(),
ggplot(df, aes(x = factor(1), fill = nivelest)) + geom_bar(width = 1) + coord_polar(theta = "y") + theme_void(),
nrow=1)

Si usamos SPSS, tanto tablas de frecuencias como los gráficos mencionados los encontramos en la opción de menú “Analizar – Estadísticos Descriptivos – Frecuencias”.

1.1.2 Datos Numéricos.

Los datos numéricos son mucho más ricos en información que los datos categóricos. Por tanto además de las tablas, tenemos otras medidas que sirven para resumir la información que contienen. Dependiendo de cómo se distribuyan los datos, usaremos grupos de medidas de resumen diferentes.

Cuando se tiene una variable numérica, lo primero que nos puede interesar es alrededor de qué valor se agrupan los datos, y cómo se dispersan con respecto a él.

En múltiples ocasiones los datos presentan cierta distribución acampanada como la de la figura adjunta, denominada distribución normal. En estos casos con sólo dos medidas como son la media y la desviación típica tenemos resumida prácticamente toda la información contenida en las observaciones.

sjp.frq(df$talla, type = "hist", show.mean = TRUE,normal.curve = TRUE)

La media: es el promedio de todos los valores de la variable, es decir, la suma de todos los datos dividido por el número de ellos. La desviación típica (S) nos da una medida de la dispersión que tienen los datos con respecto a la media. En datos de distribución acampanada (aproximadamente normal), ocurre lo siguiente:

  • Entre la media y a una distancia de una desviación típica se encuentra (aproximadamente) el 68% central de los datos.

  • Entre la media y a una distancia de dos desviación típica se encuentra (aproximadamente) el 95% central de los datos.

Sigue este enlace para practicar con la desviación típica

La media y la desviación muestral no tienen tanto interés cuando los datos presentan largas colas u observaciones anómalas (outliers), es decir, son muy influenciables por las asimetrías y los valores extremos. En estos casos, debemos considerar medidas más resistentes a estas influencias.

grid.arrange(
sjp.frq(df$peso, type = "hist", show.mean = TRUE,normal.curve = TRUE)+coord_cartesian(xlim=c(40,160)),
sjp.frq(df$peso, type = "boxplot", show.mean = TRUE,normal.curve = TRUE) + 
  coord_cartesian(ylim=c(40,160))+ coord_flip(), nrow=2)

Como medidas de centralización resistentes podemos utilizar en sustitución de la media:

  • La mediana, que es aquel valor que deja la mitad de los datos por debajo de él.

  • La media recortada (trimmed mean), muy utilizada en datos preferentemente simétricos, con muchas observaciones anómalas y, que se obtiene eliminando un determinado porcentaje de los datos menores y mayores; Así calculamos la media sin contar con ese porcentaje de datos extremos, haciendo desaparecer su influencia.

En cuanto a las medidas de dispersión más resistentes podemos utilizar el rango intercuartílico (IQR), que es la diferencia entre el tercer cuartil y el primero. El primer cuartil (Q1) deja al 25% de los datos por debajo de él y el tercer cuartil (Q3) deja al 75%, por tanto sabemos que entre ambos valores se encuentra el 50% central de las observaciones.

Para practicar con percentiles sigue este enlace

Ahora bien, ¿qué criterios aproximados podemos utilizar para clasificar unos datos como normales o no? Para ello destacamos varias características de la distribución normal. El alejamiento de las mismas es indicación de falta de normalidad:

  • Es simétrica (el coeficiente de asimetría vale cero)
  • Tiene forma de campana (el apuntamiento o curtosis vale cero).
  • Coinciden la media y la mediana
  • Aproximadamente el 95% de las observaciones se encuentran en el intervalo de centro la media y radio dos veces la desviación típica.

Los indicadores que miden la simetría y la forma de la campana son el coeficiente de asimetría (skewness) (negativo en distribuciones con cola a la izquierda, positivo en distribuciones con cola a la derecha) y la curtosis (kurtosis) (negativa para las aplanadas y positiva para las apuntadas).

generaTablaDescriptivaNumericas(df,c("edad","peso","talla","imc"),
               columnas = c("n", "media","dt","min","p25","p50","p75","max","asim","curtosis")) %>%
  kable(booktabs=T)
Variable n media dt p25 p50 p75 asim curtosis
edad 536 65 10.4 58 65 72 -0.20 0.07
peso 430 77 13.4 69 76 85 0.92 2.69
talla 354 159 9.7 152 158 165 0.26 -0.04
imc 351 31 5.2 28 30 33 1.03 2.02
grid.arrange(
ggplot(df,aes(x=edad))+geom_histogram(),
ggplot(df,aes(x=talla))+geom_histogram(),
ggplot(df,aes(x=peso))+geom_histogram(),
ggplot(df,aes(x=imc))+geom_histogram(),
nrow=2)

En la tablas anteriores, así como en los gráficos (llamados histogramas) vemos como peso e IMC presentan una cierta falta de normalidad; Podríamos entonces presentar un resumen de estas variables del siguiente modo:

tabla=KreateTableOne(data = df %>% select(edad,talla,peso,imc),nonnormal=c("peso","imc"))
tabla %>% knitr::kable(booktabs=TRUE)
Overall
n 536
edad (mean (sd)) 65.19 (10.39)
talla (mean (sd)) 158.68 (9.71)
peso (median [IQR]) 76.00 [69.00, 84.57]
imc (median [IQR]) 30.12 [27.61, 33.20]

La falta de normalidad no es fácil de apreciarlo mirando directamente el histograma. Hay gráficos como el Q-Q plot, que nos indican la falta de normalidad como desviaciones de la observaciones con respecto a una línea recta:

grid.arrange(
ggplot(df, aes(sample =edad))  +  stat_qq() + stat_qq_line()+ggtitle("edad"),
ggplot(df, aes(sample =talla))  +  stat_qq() + stat_qq_line()+ggtitle("peso"),
ggplot(df, aes(sample =peso)) + stat_qq() +  stat_qq_line()+ggtitle("talla"),
ggplot(df, aes(sample =imc))   +  stat_qq() + stat_qq_line()+ggtitle("imc"), 
nrow=2)

Las medida mencionadas podemos calcularlas con SPSS en el menú “Analizar – Estadísticos Descriptivos – Frecuencias” y pulsando el botón “Estadísticos…”, o bien podemos usar el menú “Analizar - Estadísticos descriptivos - Explorar”, donde podemos añadir los gráficos con pruebas de normalidad.

1.2 Datos bivariantes

Si resumir la información de una variable es de por sí interesante, en investigación lo es mucho más el poner de manifiesto la posible relación entre dos de ellas:

¿Hay relación entre el tabaco y el cáncer de pulmón? ¿Aumentando la dosis de un medicamento, mejoramos la respuesta?

Para ello realizamos estudios donde intervienen ambas variables simultáneamente. Según sean los tipos de cada una de ellas usaremos técnicas diferentes.

1.2.1 Categórica-categórica

Cuando ambas variables son categóricas (o discretas con pocas modalidades), se suele presentar las observaciones en una tabla de contingencia. Esta una tabla de doble entrada donde se presentan la distribución de frecuencias conjunta de las dos variables.

Continuando con la base de datos del ejemplo, podríamos estudiar qué distribución presentan otras variables cualitativas según el sexo del paciente. Lo mostraríamos como sigue:

tabla=KreateTableOne(vars = c("tabaco","estcivil","sedentar","diabm","hipercol"), strata = "sexo" , data = df)
tabla %>% knitr::kable(booktabs=T)
Hombre Mujer p test
n 218 318
tabaco (%) <0.001
No fuma 43 (20.8) 90 (28.8)
Ex fumador (10+) años 30 (14.5) 2 ( 0.6)
Ex fumador (9-) años 70 (33.8) 202 (64.5)
Fumador 64 (30.9) 19 ( 6.1)
estcivil (%) <0.001
Soltero 7 ( 3.2) 15 ( 4.7)
Casado/pareja 191 (87.6) 188 (59.3)
Separado 5 ( 2.3) 12 ( 3.8)
Viudo 15 ( 6.9) 102 (32.2)
sedentar = No (%) 81 (47.9) 100 (37.9) 0.049
diabm = No (%) 157 (73.0) 212 (66.9) 0.158
hipercol = No (%) 162 (74.7) 211 (67.4) 0.089

En la tabla anterior hay una columna denominada p (significación) que será my importante en temas posteriores.

En cuanto a la representación gráfica, podemos utilizar el diagrama de barras apiladas o agrupadas, aunque en ellos no es inmediato apreciar las diferencias por sexos

grid.arrange(
sjp.grpfrq(df$tabaco, df$sexo,show.prc = FALSE),
sjp.grpfrq(df$estcivil, df$sexo,,show.prc = FALSE),
sjp.grpfrq(df$sedentar, df$sexo,show.prc = FALSE),
sjp.grpfrq(df$diabm, df$sexo,show.prc = FALSE),
sjp.grpfrq(df$hipercol, df$sexo,show.prc = FALSE),ncol=1)

Desglosando en cada categoría de la variable los porcentajes de cada sexo es más sencillo de ver:

dftmp=df %>% select(sexo,tabaco)%>% filter(!is.na(tabaco)) %>% 
  mutate(cuenta=1) %>% group_by(sexo,tabaco) %>% 
  tally() %>% mutate(fraccion=n/sum(n))
ggplot(dftmp, aes(fill=sexo, y=fraccion, x=tabaco)) + 
    geom_bar( stat="identity", position="fill")

dftmp=df %>% select(sexo,diabm) %>% filter(!is.na(diabm)) %>% mutate(cuenta=1) %>% group_by(sexo,diabm) %>% tally() %>% mutate(fraccion=n/sum(n))
ggplot(dftmp, aes(fill=sexo, y=fraccion, x=diabm)) + 
    geom_bar( stat="identity", position="fill")

1.2.2 Categórica-Numérica

Supongamos que tenemos datos numéricos para varias categorías. Por ejemplo, en un experimento donde hacemos mediciones numéricas en dos grupos: uno al que se le aplica determinado tratamiento y otro de control. Podemos describir los resultados del experimento con sólo dos variables: Una variable categórica que representa el grupo de tratamiento, y otra que representa el resultado numérico

En estos casos, lo que se realiza es un estudio descriptivo de la variable numérica en cada una de las muestras y comparamos los resultados.

Volviendo a nuestro ejemplo, vamos a comparar las variables numéricas de la base de datos entre sexos:

tabla=KreateTableOne(vars = c("edad", "talla","peso","imc"), strata = "sexo" , data = df) 
tabla %>% knitr::kable(booktabs=T)
Hombre Mujer p test
n 218 318
edad (mean (sd)) 63.85 (10.70) 66.11 (10.08) 0.013
talla (mean (sd)) 167.03 (7.22) 153.70 (7.28) <0.001
peso (mean (sd)) 80.90 (13.13) 75.03 (13.07) <0.001
imc (mean (sd)) 29.12 (3.82) 31.84 (5.54) <0.001
tabla=KreateTableOne(data=df,vars = c("edad","peso","talla","imc","pas","pad","fc"), strata = "tabaco" ) 
tabla %>% knitr::kable(booktabs=T)
No fuma Ex fumador (10+) años Ex fumador (9-) años Fumador p test
n 133 32 272 83
edad (mean (sd)) 67.14 (9.28) 64.09 (8.19) 66.13 (10.75) 59.36 (9.81) <0.001
peso (mean (sd)) 77.77 (14.44) 79.97 (10.46) 75.75 (13.24) 80.56 (12.94) 0.053
talla (mean (sd)) 158.10 (9.73) 165.67 (5.25) 155.94 (8.70) 167.13 (9.03) <0.001
imc (mean (sd)) 31.15 (5.11) 29.00 (2.72) 31.39 (5.59) 29.10 (3.56) 0.022
pas (mean (sd)) 149.11 (18.69) 133.03 (13.88) 142.10 (17.51) 140.72 (16.66) <0.001
pad (mean (sd)) 81.00 (11.05) 81.84 (9.96) 81.24 (10.61) 84.20 (10.06) 0.127
fc (mean (sd)) 74.93 (12.10) 58.66 (33.20) 58.25 (29.20) 64.35 (28.23) <0.001

En las tablas anteriores aparecen de nuevos las cantidades p (significación) de las que hablaremos más adelante.

Los diagramas de cajas muestran los cuartiles en unas cajas centrales, así como observaciones más alejadas, y permiten hacerse una idea visual de qué diferencias existen entre los grupos. Por ejemplo, en las tablas anteriores se apreciaba una cierta diferencia de talla entre hombres y mujeres, aunque no así en pad:

grid.arrange(
ggplot(df,aes(x=sexo,y=talla))+geom_boxplot(),
ggplot(df,aes(x=sexo,y=pad))+geom_boxplot(),ncol=2)

Si usamos SPSS, tenemos a nuestra disposición la opción de menú “Analizar – Estadísticos descriptivos – Explorar…”. En la casilla denominada “dependientes” situamos la variable numérica y en “factores” situamos la categórica.

1.2.3 Numérica-Numérica.

Cuando hablamos de comparar dos variables numéricas, pensamos en establecer la posible relación entre ellas.

¿Estarán relacionados la altura y el peso de los individuos? ¿Cuanto mayor es el tamaño del cerebro, mayor es el coeficiente intelectual?

La vía más directa para estudiar la posible asociación consiste en inspeccionar visualmente un diagrama de dispersión (nube de puntos). Si reconocemos una tendencia, es una indicación de que puede valer la pena explorar con más profundidad. Si es el caso, puede interesarnos proseguir con un análisis de regresión. En este tipo de análisis se pretende encontrar un modelo matemático (recta de regresión) que explique los valores de una de las variables (dependiente) en función de la otra (independiente). A ello le dedicamos un capítulo con posterioridad.

Por ejemplo, en la base de datos con que trabajamos, es lógico esperar una buena relación entre el peso y el imc, y eso es justo lo que encontramos.

ggplot(df, aes(x=peso, y=imc)) + geom_jitter(alpha=0.3)

En otras variables la relación no es tan evidente, como la que existe entre edad y mayor presión arterial diastólica y menor presión arterial sistólica. Las rectas de regresión no serán muy útiles para percibir la tendencia con más facilidad (aunque esto solo lo utilizamos ahora como ayuda visual).

grid.arrange(
  ggplot(df, aes(x=edad, y=pas)) + geom_jitter(alpha=0.3)+geom_smooth(method="lm"),
ggplot(df, aes(x=edad, y=pad)) + geom_jitter(alpha=0.3)+geom_smooth(method="lm"),nrow=1)

Para describir numéricamente el grado de asociación lineal dentre variables numéricas suele usarse el coeficiente de correlación lineal de Pearson (r). Esta es una cantidad adimensional que toma valores entre -1 y 1. Cuando r=0 se dice que hay incorrelación (nada de asociación lineal). Cuánto más se aleje r de cero, mayor es el grado de asociación lineal entre las vaiables.

Para practicar con el coeficiente de correlación lineal de Pearson, siga este enlace

Los gráficos mostrados se realizan en SPSS en el menú: “Gráficos – Dispersión… – Simple“. El coeficiente de correlacion lineal de Pearson lo encontramos en el menú:”Analizar - Correlaciones - Bivariadas”.

Si queremos mostrar todas las correlaciones existentes entre las variables numéricas de nuestra base de datos, tendremos un r que mostrar por cada par de variables. Eso hace una buena cantidad de números. Una forma habitual de mostrarlos sin ocupar mucho espacio es esta:

df %>% generaTablaCorrelaciones(vNumericas = c("edad","peso","talla","imc","pas","pad","fc")) %>%
  knitr::kable(booktabs=T)
Variable edad [01] [02] [03] [04] [05]
[01] peso -0.28***
[02] talla -0.32*** 0.44***
[03] imc -0.06 0.73*** -0.27***
[04] pas 0.22*** 0.02 -0.12* 0.12*
[05] pad -0.24*** 0.13** 0.10 0.07 0.39***
[06] fc 0.01 -0.02 -0.08 0.03 0.08 0.07