x <- c(0, 1, 2, 0, 1, 1, 0, 0, 2, 2, 3)
mean(x)[1] 1.090909
Cuadernos prácticos del Máster de Bioinformática (curso 2024-2025)
La estadística descriptiva es una rama de la estadística que se dedica a recolectar, organizar, presentar y analizar un conjunto de datos para describir las características y comportamientos de dicho conjunto.
Además de para conocer y entender los datos es la fase en la que detectaremos errores e incongruencias, teniendo muchas veces que hacer una depuración de datos para dejar la base de datos preparada para su análisis.
La podemos hacer a través de encuestas, experimentos, observaciones, registros, etc. Lo más importante en esta etapa es que los datos sean representativos del fenómeno o población que se estudia.
Ejemplo: queremos llevar a cabo una investigación para analizar la satisfacción de los pacientes con los servicios de urgencias de la red de hospitales públicos madrileños. ¿Qué muestra será más representativa?
Los 100 primeros pacientes que lleguen a las urgencias del Hospital 12 de Octubre.
Los 10 primeros pacientes que lleguen a las urgencias de todos los hospitales de la red de hospitales madrileños.
Seleccionamos al azar 3 hospitales del grupo 3 (hospitales de gran complejidad), grupo 2 (hospitales de complejidad intermedia) y grupo 3 (hospitales de baja complejidad) y de cada uno de ellos seleccionamos un número proporcional de pacientes según el número total de pacientes que llegan a cada hospital.
Solución:
Con a) todas las conclusiones que saquemos del estudio serán aplicadas al Hospital 12 de Octubre. Con b) es una forma semi representativa pero válida de conseguir una muestra de forma fácil. La rama de la estadística que se dedica a estudiar esta parte del análisis se conoce como muestreo
Una vez recopilados los datos deben organizarse de manera que sean comprensibles y manejables. Para ello necesitaremos clasificar los datos en cuantitativos y cualitativos y estudiar sus características según su tipo.
Messy data: datos mal organizados o desordenados (múltiples individuos en cada fila, misma variable pero separada en varias columnas, etc).
Tidy data: datos organizados y estandarizados (una variable en cada columna, un registro/individuo en cada fila y un solo valor en cada celda).
La información la poder resumir o presentar de distintas maneras.
Estadísticos o medidas:
Medidas cualitativas: tablas de frecuencias.
Medidas cuantitativas: medidas numéricas de centralización y dispersión.
Gráficamente:
Medidas cualitativas: gráficos de barras, gofres, etc.
Medidas cuantitativas: histogramas, densidades, boxplots, etc
Una vez hecho el estudio de cada variable por separado buscaremos relacionar dos variables de forma simultánea para buscar la asociación entre ellas:
Cuali vs cuali: tablas de frecuencias –> pruebas de Fisher y chi-cuadrado –> interpretación de OR y RR.
Cuanti vs cuanti: correlación –> test de correlaciones (o test de igualdad de distribuciones) –> diagrmas de dispersión.
Cuanti vs cuali: ANOVA, biserial correlation, etc.
En estadística es fundamental entender los conceptos de población, muestra y variable, ya que son la base para cualquier análisis estadístico.
La población es el conjunto completo de elementos o individuos que tienen una característica común y sobre los cuales se desea obtener información. En la mayoría de casos el acceso a la totalidad de la población es inviable por motivos económicos, legales o éticos, así que en la mayoría de situaciones las conclusiones deberemos sacarlas haciendo uso de lo que se conoce como muestra.
Ejemplo: la diferencia entre censo y encuesta es que el primero recopila datos de todos los individuos de una población, mientras que el segundo trata de estimarlos o inferirlos a partir de una muestra representativa de la misma.
Una muestra es un subconjunto de la población que se selecciona para su análisis con el fin de hacer inferencias o generalizaciones sobre la población completa. La muestra debe ser representativa de la población para que las conclusiones sean válidas.
Muestreo aleatorio simple: cada miembro de la población tiene la misma probabilidad de ser seleccionado.
Muestreo estratificado: la población se divide en subgrupos (estratos) y se toma una muestra de cada uno.
Muestreo (no aleatorio) sistemático: se selecciona cada n-ésimo miembro de la población.
Muestreo (no aleatorio) por cuotas: se seleccionan aquellos individuos que cumplan ciertas condiciones.
Muestreo por conveniencia: se elige a los miembros que son más fáciles de acceder, aunque este método puede introducir sesgos.
Veamos algunos ejemplos:
Ejemplo 1
Población: todos los pacientes que han sido atendidos en un hospital específico durante el último año.
Muestra (aleatoria simple): Seleccionamosseleccionamos 200 pacientes de manera aleatoria del registro de pacientes del último año. Para asegurarnos de que la muestra sea representativa, podemos usar muestreo aleatorio simple, donde cada paciente tiene la misma probabilidad de ser seleccionado.
Ejemplo 2
Población: todos los estudiantes matriculados en una universidad durante el semestre actual.
Muestra (aleatoria estratificada): seleccionamos 500 estudiantes utilizando muestreo estratificado para asegurar que diferentes subgrupos (estratos) de la población estén representados. Los estratos pueden ser facultades (mismo % de facultades representadas que en la población universitaria), género, clase social, etc.
Ejemplo 3
Población: todas las especies de árboles en un bosque determinado.
Muestra (sistemática no aleatoria): Sseleccionamos parcelas de muestreo de 10m x 10m dentro del bosque y contabilizamos todas las especies de árboles presentes en esas parcelas. Esto se puede hacer utilizando muestreo sistemático.
Ejemplo 4
Población: todos los pacientes de covid de un hospital.
Muestra (por cuotas no aleatoria): seleccionamos solo a las personas mayores de 65 años para realizar un estudio clínico inicial sobre los efectos secundarios de una posible vacuna de la covid-19.
Estos métodos aseguran, de una manera u otra, que las muestras sean representativas de sus respectivas poblaciones, lo que permite realizar análisis precisos y confiables.
Una variable es cualquier característica o atributo que puede tomar diferentes valores entre los individuos de la población o muestra. Las variables pueden ser de varios tipos según su naturaleza:
Cualitativas (o categóricas): describen cualidades o categorías. Ejemplos:
Cuantitativas: describen cantidades y pueden ser medidas numéricamente. Ejemplos:
Modalidades
Una modalidad es uno de los valores que toma una variable dentro de una muestra.
El conjunto de modalidades posibles que podría haber tomado (en tu población) se suele conocer también como soporte. Algunos ejemplos en función del tipo de variables son:
Una modalidad es uno de los valores que toma una variable dentro de una muestra. El conjunto de modalidades posibles que podría haber tomado (en tu población) se suele conocer también como soporte. Algunos ejemplos en función del tipo de variables son:
Número de hijos (cuantitativa discreta finita): 0, 1, 2 y 3 (4 modalidades en esa muestra de un conjunto de valores posibles - de 0 a…20 hijos - que podríamos tener en la población general).
Temperatura anual de Madrid (cuantitativa continua): un rango de -5ºC a 45ºC (un rango continuo de valores en los que se mueve nuestra variable en la muestra (de un rango más amplio, por ejemplo desde -20ºC a 50ºC que podría moverse de manera global si tuviésemos otra muestra).
Veamos algunos ejemplos: piensa en tipos de variables que se pueden medir en cada uno de los ejemplos de población y muestra que hemos estudiado.
| Población | Muestra | Variables |
|---|---|---|
| Todos los pacientes de un hospital de los queremos estudiar su grado de satisfcacción con la atención que han recibido | 200 pacientes seleccionados de forma aleatoria del registro de pacientes en el último año | Cuantitativas: Cualitativas: |
| Población | Muestra | Variables | |
|---|---|---|---|
| Todos los pacientes de un hospital de los queremos estudiar su grado de satisfcacción con la atención que han recibido | 200 pacientes seleccionados de forma aleatoria del registro de pacientes en el último año | Cuantitativas: edad (discreta), tiempo de espera (continua), grado de satisfacción en una escala del 0 al 10 (discreta), número de visitas en el último año (discreta). | Cualitativas: género (nominal), estado civil (nominal), si viene acompañado (nominal), grado de satisfacción como bueno, regular malo (ordinal). |
| Población | Muestra | Variables |
|---|
| Población | Muestra | Variables |
|---|---|---|
| Todos los estudiantes matriculados en una universidad de los que queremos estudiar las calificaciones obtenidas | 500 estudiantes de las diferentes facultades | Cuantitativas: calificaciones, edad (discreta), número de veces que se ha presentado al examen (discreta). Cualitativas: asignaturas (nominal), facultad (nominal). |
| Población | Muestra | Variables |
|---|
| Población | Muestra | Variables |
|---|---|---|
| Especies de árboles en un bosque de los que queremos estudiar su estado de salud | Selección sistemática de parcelas de 10m x 10m dentro del bosque | Cuantitativas: altura del árbol (continua), diámetro del árbol (continua), edad del árbol (discreta). Cualitativas: especie del árbol (nominal), estado de salud (ordinal), tipo de suelo (nominal). |
Nos referimos a las medidas con las que se pretende resumir y condensar la información contenida en un conjunto de datos. Las mayoría de características numéricas las mediremos en variables cuantitativas.
Son los valores que resumen el conjunto de los datos de forma que reflejan el centro de la distribución de la tabla de frecuencias
Es el valor medio o centro de gravedad (el valor más cercano a todos los puntos a la vez). Es la suma de todos los valores dividida por el número total de valores.
\[\bar x= \frac{\sum^n_{i=1} x_i}{n}\]
A los enfermeros de un centro de salud se les pregunta por el nº de hijos que tienen. Sus respuestas son 0,1,2,0,1,1,0,0,2,2,3. ¿Cuál es su media?
\(n=11\)
\(\sum^n_{i=1} x_i = 0+1+2+0+1+1+0+0+2+2+3 = 12\)
\(\bar x= \frac{\sum^n_{i=1} x_i}{n} = \frac{12}{11} = 1.09\) hijos
x <- c(0, 1, 2, 0, 1, 1, 0, 0, 2, 2, 3)
mean(x)[1] 1.090909
A los enfermeros de un centro de salud se les pregunta por el nº de hijos que tienen. Sus respuestas son 0,1,2,0,1,1,0,0,2,2,3,10. ¿Cuál es su media?
\(\bar x= \frac{\sum^n_{i=1} x_i}{n} = \frac{22}{12} = 1.83\) hijos
x <- c(0, 1, 2, 0, 1, 1, 0, 0, 2, 2, 3, 10)
mean(x)[1] 1.833333
La media es una medida útil y ampliamente aplicada de la tendencia central, pero debe ser utilizada con precaución en conjuntos de datos que contienen valores atípicos o están distribuidos de manera asimétrica.
Es el valor del medio SIEMPRE Y CUANDO ordenemos los datos. Divide la distribución de frecuencias en dos partes.
Para calcularla debemos realizar los siguientes pasos:
Ordenar los datos en orden creciente
Según el número de observaciones (n):
Si n es impar: La mediana es el valor que ocupa la posición central
Si n es par: La mediana es el promedio de los dos valores central
Ejemplo 1: variables cuantitativas (número impar)
Datos: 3, 1, 4, 2, 5 (n=5)
Ordenados: 1, 2, 3, 4, 5
Mediana: 3 (el tercer valor)
Ejemplo 2: variables cuantitativas (número par)
Datos: 7, 2, 4, 6 (n=4)
Ordenados: 2, 4, 6, 7
Mediana: (4 + 6) / 2 = 5
Ejemplo 3: variables cualitativas (ordinales)
Datos: “notable”, “suspenso”, “sobresaliente”, “suspenso”, “notable”, “aprobado”, “notable” (n=7).
Ordenados: “suspenso”, “suspenso”, “aprobado”, “notable”, “notable”, “notable”, “sobresaliente”.
Mediana: “notable”.
La mediana es especialmente útil en distribuciones asimétricas o cuando se quiere una medida de tendencia central que no sea afectada por valores extremadamente altos o bajos.
A los enfermeros de un centro de salud se les pregunta por el nº de hijos que tienen. Sus respuestas son 0,1,2,0,1,1,0,0,2,2,3. ¿Cuál es su mediana?
\(n=11\)
Ordenados: 0,0,0,0,1,1,1,2,2,2,3
Mediana: Posición 6 = 1 hijo
x <- c(0,1,2,0,1,1,0,0,2,2,3)
median(x)[1] 1
A los enfermeros de un centro de salud se les pregunta por el nº de hijos que tienen. Sus respuestas son 0,1,2,0,1,1,0,0,2,2,3,10. ¿Cuál es su mediana?
\(n=12\)
Ordenados: 0,0,0,0,1,1,1,2,2,2,3,10
Mediana: Posición 6 y 7 = 1 +1 /2 = 1 hijo
x <- c(0,1,2,0,1,1,0,0,2,2,3, 10)
median(x)[1] 1
Es el valor que presenta la máxima frecuencia y se puede calcular para todas las variables (también) cualitativas. Es más, es un valor que suele usarse en el análisis de variables cualitativas.
Unimodal:
Bimodal:
Multimodal:
Sin moda:
A los enfermeros de un centro de salud se les pregunta por el nº de hijos que tienen. Sus respuestas son 0,1,2,0,1,1,0,0,2,2,3. ¿Cuál es su moda?
library(tidyverse)── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.1.4 ✔ readr 2.1.5
✔ forcats 1.0.0 ✔ stringr 1.5.1
✔ ggplot2 3.5.1 ✔ tibble 3.2.1
✔ lubridate 1.9.3 ✔ tidyr 1.3.1
✔ purrr 1.0.2
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
datos <- tibble("x" = c(0,1,2,0,1,1,0,0,2,2,3))
datos |>
count(x)# A tibble: 4 × 2
x n
<dbl> <int>
1 0 4
2 1 3
3 2 3
4 3 1
La modalidad más frecuente es 0 por lo que la moda es 0.
Los cuantiles son valores que dividen un conjunto de datos en partes iguales según la distribución de los datos (de nuevo asumiento que tenemos los datos ordenados de menor a mayor). Los cuantiles son útiles para comprender la distribución y la dispersión de los datos. Existen diferentes tipos de cuantiles, cada uno con un número específico de divisiones:
Cuartiles: dividen el conjunto de datos en cuatro partes iguales.
Primer cuartil (Q1): divide el 25% inferior de los datos del 75% superior.
Mediana (Q2): divide el 50% inferior del 50% superior. Es el segundo cuartil.
Tercer cuartil (Q3): divide el 75% inferior del 25% superior.
Deciles: dividen el conjunto de datos en diez partes iguales.
Primer decil (D1): divide el 10% inferior del 90% superior.
Segundo decil (D2): divide el 20% inferior del 80% superior.
Y así sucesivamente hasta el noveno decil (D9), que divide el 90% inferior del 10% superior.
Percentiles: dividen el conjunto de datos en cien partes iguales.
Percentil 1 (P1): divide el 1% inferior del 99% superior.
Percentil 2 (P2): divide el 2% inferior del 98% superior.
Y así sucesivamente hasta el percentil 99 (P99), que divide el 99% inferior del 1% superior.
Supongamos que tenemos el siguiente conjunto de datos (que podemos ordenar): 10, 25, 4, 2, 14, 6, 18, 16, 8, 12, 20. ¿Cuáles son sus cuartiles?
datos <- tibble("x" = c(10, 25, 4, 2, 14, 6, 18, 16, 8, 12, 20))
datos |>
reframe("cuartiles" = quantile(x))# A tibble: 5 × 1
cuartiles
<dbl>
1 2
2 7
3 12
4 17
5 25
Medidas (solo disponibles para cuantitativas) que nos indican cómo de lejos o cerca están las observaciones del valor central que hemos calculado, es decir cuánto se alejan de la media o mediana: nos indican el grado de dispersión de la distribución de frecuencias.
Indica la diferencia entre el valor máximo y el valor mínimo en un conjunto de datos.
A los enfermeros de un centro de salud se les pregunta por el nº de hijos que tienen. Sus respuestas son 0,1,2,0,1,1,0,0,2,2,3. ¿Cuál es su recorrido?
Valor máximo = 3
Valor mínimo = 0
Recorrido= 3-0 = 3
x <- c(0,1,2,0,1,1,0,0,2,2,3)
max(x)- min(x)[1] 3
A los enfermeros de un centro de salud se les pregunta por el nº de hijos que tienen. Sus respuestas son 0,1,2,0,1,1,0,0,2,2,3,10. ¿Cuál es su recorrido?
Valor máximo = 10
Valor mínimo = 0
Recorrido= 10-0 = 10
x <- c(0,1,2,0,1,1,0,0,2,2,3, 10)
max(x) - min(x)[1] 10
El recorrido es útil cuando se necesita una medida rápida y simple de la dispersión, pero para análisis más detallados y robustos, se utilizan otras medidas de dispersión como la desviación estándar, la varianza o el rango intercuartílico.
Mide la amplitud del 50% central de un conjunto de datos. Se calcula como la diferencia entre el tercer cuartil (Q3) y el primer cuartil (Q1), proporcionando una medida robusta de la variabilidad de los datos al no ser afectada por valores atípicos o extremos.
\[IQR = Q_3 - Q_1\]
Cuantifica cuánto varían los datos respecto a la media del conjunto. Una varianza alta indica que los datos están más dispersos alrededor de la media, mientras que una varianza baja indica que los datos están más agrupados cerca de la media. Importante: medimos las desviaciones al cuadrado para que no se cancelen signos.
\[s^2 = \frac{\sum_{i=1}^n (x_i - \bar x)^2}{n-1}\]
\(x_i\) representa cada valor individual en el conjunto de datos.
\(\bar x\) es la media de la muestra.
\(n\) es el tamaño de la muestra.
Es la raíz cuadrada de la varianza y se calcula de la siguiente manera:
\[s = \sqrt {s^2} = \sqrt {\frac{\sum_{i=1}^n (x_i - \bar x)^2}{n-1}}\]
La desviación estándar se interpreta en las mismas unidades que los datos originales, lo que la hace más intuitiva que la varianza. Indica la dispersión promedio de los datos respecto a la media. Fíjate que en las medidas de dispersión el promedio lo estamos realizando diviendo entre n-1 y no entre n. Esto es debido a que los parámetros que hemos visto hasta ahora se conocen con un apellido: parámetros muestrales (calculados con los datos disponibles en una muestra).
El objetivo con ellos es aproximar los verdaderos parámetros poblacionales (la media real de la población, no la que calculas con tu tabla), y el mejor estimador posible de la varianza población (se conoce como estimador insesgado, sin sesgo) es la que hemos definido dividiendo entre n-1, de ahí que todos los softwares estadísticos nos calculen dicho valor (se la conoce también como cuasivarianza).
A los enfermeros de un centro de salud se les pregunta por el nº de hijos que tienen. Sus respuestas son 0,1,2,0,1,1,0,0,2,2,3. ¿Cuál es su varianza y desviación típica?
x <- c(0,1,2,0,1,1,0,0,2,2,3)
var(x)[1] 1.090909
sd(x)[1] 1.044466
A los enfermeros de un centro de salud se les pregunta por el nº de hijos que tienen. Sus respuestas son 0,1,2,0,1,1,0,0,2,2,3,10. ¿Cuál es su varianza y desviación típica?
x <- c(0,1,2,0,1,1,0,0,2,2,3, 10)
var(x)[1] 7.606061
sd(x)[1] 2.757909
Uno de los problemas al comparar dispersiones de dos variables diferentes es que tanto la varianza como la desviación típica dependen de la escala de los datos.
Esto implica que una desviación de, por ejemplo, 0.5, puede representar una dispersión pequeña (si el rango de mis datos está entre 100 y 200, por ejemplo) pero puede representar una dispersión enorme si el rango de mis datos es también pequeño (por ejemplo, datos entre 0 y 1).
Para poder comparar dispersiones de variables de diferentes rangos (o incluso unidades) existe el conocido como coeficiente de variación (CV):
\[CV = \frac s {|\bar x|}\]
El coeficiente de variación es siempre adimensional y positivo.
Las variables cualitativas o cuantitativas discretas las vamos a poder resumir en tablas de frecuencias o de contigencia donde se ordenan y estructuran los valores de una variable x de forma resumida de la siguiente manera:
Frecuencia absoluta de x: nº de veces que se repite cada modalidad de x.
Frecuencia relativa de x: proporción de veces que se repite cada modalidad de x.
Frecuencia absoluta acumulada de x: nº de observaciones menores o iguales que cada modalidad de x (solo apto para cuantitativas o cualitativas ordinales ya que necesitamos una estructura de orden).
Frecuencia relativa acumulada de x: proporción de valores menores o iguales que cada modalidad de x (solo apto para cuantitativas o cualitativas ordinales ya que necesitamos una estructura de orden).
| Valores de la variable | Frecuecias Absolutas | Frecuencias relativas | Frecuencias Absolutas acumuladas | Frecuencias Relativas acumuladas |
|---|---|---|---|---|
| \(x_i\) | \(f_i\) | \(p_i\) | \(F_i\) | \(P_i\) |
En un estudio sobre el grupo sanguíneo realizado con \(n = 6313\) individuos se obtuvo la siguiente tabla de frecuencias La variable tiene \(k = 4\) modalidades (O, A, B, AB).
| Valores de la variable | Frecuecias Absolutas | Frecuencias relativas | Frecuencias Absolutas acumuladas | Frecuencias Relativas acumuladas |
|---|---|---|---|---|
| \(x_i\) | \(f_i\) | \(p_i\) | \(F_i\) | \(P_i\) |
| O | 2892 | 2892/6313 = 0.458 | 2892 | 0.458 |
| A | 2625 | 1625/6313 = 0.416 | 5517 | 0.874 |
| B | 570 | 570/6313 = 0.09 | 6087 | 0.964 |
| AB | 226 | 226/6313 = 0.036 | 6313 | 1 |
| TOTAL | 6313 | 1 | 6313 | 1 |
\[\sum^k_{i=1} f_i=n\] \[\sum^k_{i=1} p_i = 1\]
¿Qué conclusiones sacarías al ver esta tabla?
La gran mayoría de esta muestra tiene grupo sanguíneo O ó A con un 46% y 42% respectivamente y que los grupos B y AB son minoritarios, siendo el AB la modalidad minoritaria.
Otro ejemplo: las edades en un grupo de \(n = 25\) estudiantes universitarios
| Valores de la variable | Frecuecias Absolutas | Frecuencias relativas | Frecuencias Absolutas acumuladas | Frecuencias Relativas acumuladas |
|---|---|---|---|---|
| \(x_i\) | \(f_i\) | \(p_i\) | \(F_i\) | \(P_i\) |
| 18 | 6 | 0.24 | 6 | 0.24 |
| 19 | 5 | 0.20 | 11 | 0.44 |
| 20 | 3 | 0.12 | 14 | 0.56 |
| 21 | 3 | 0.12 | 17 | 0.68 |
| 22 | 3 | 0.12 | 20 | 0.80 |
| 23 | 3 | 0.12 | 23 | 0.92 |
| 24 | 2 | 0.08 | 25 | 1 |
| Total | 25 | 1 | 25 | 1 |
Contesta a las siguientes preguntas sobre la tabla anterior:
¿Cuántos individuos tienen 21 años?
¿Qué porcentaje de individuos tiene más de 19 años?
¿Qué pasa cuando tenemos una variable cuantitativa continua?
Imagina que anotamos las puntuaciones obtenidas por 100 pacientes en un test psicológico en una escala continua del 0 al 100.
\(x_i\): 11,42,58,25,48,18,45,35,59,29,35,2,37,68,70,31,44,84,64,82,26,42,51,29, 59,92,56,5,52,8,1,12,21,6,32,15,67,47,61,47,43,33,48,47,43,69,49,21,9,15,11,22, 29,14,31,46,19,49,51,71,52,32,51,44,58,60,43,65,73,62,3,17,39,22,40,65,30,31,16, 80,41,59,60,41,51,10,63,41,74,81,20,36,59,38,40,43,18,60,71,44.
¿Tiene sentido hacer una tabla de frecuencias? ¿Nos resume la información? ¿Qué podemos hacer?
| \(x_i\) | \(f_i\) | \(p_i\) | \(F_i\) | \(P_i\) |
|---|---|---|---|---|
| [0,10] | 8 | 0.08 | 8 | 0.08 |
| (10,20] | 12 | 0.12 | 20 | 0.20 |
| (20,30] | 10 | 0.1 | 30 | 0.30 |
| (30,40] | 14 | 0.14 | 44 | 0.44 |
| (40,50] | 21 | 0.21 | 65 | 0.65 |
| (50,60] | 16 | 0.16 | 81 | 0.81 |
| (60,70] | 10 | 0.10 | 91 | 0.91 |
| (70,80] | 5 | 0.05 | 96 | 0.96 |
| (80,90] | 3 | 0.03 | 99 | 0.99 |
| (90,100] | 1 | 0.01 | 100 | 1 |
| Total | 100 | 1 |
Los resúmenes numéricos deberíamos saber hacerlos en R con datos |> summarise() pero… ¿y las tablas de frecuencia o contigencia (unidimensionales de momento)?. Por ejemplo, vamos a realizar un conteo de frecuencias de la variable hair_color de starwars. Para ello en tidyverse basta usar count()
tabla_freq <-
starwars |>
drop_na(hair_color) |>
count(hair_color)
tabla_freq# A tibble: 11 × 2
hair_color n
<chr> <int>
1 auburn 1
2 auburn, grey 1
3 auburn, white 1
4 black 13
5 blond 3
6 blonde 1
7 brown 18
8 brown, grey 1
9 grey 1
10 none 38
11 white 4
Si te fijas la frecuencia absoluta viene siempre como \(n\) pero podemos renombrarla
tabla_freq <-
tabla_freq |>
rename(frec_abs = n)
tabla_freq# A tibble: 11 × 2
hair_color frec_abs
<chr> <int>
1 auburn 1
2 auburn, grey 1
3 auburn, white 1
4 black 13
5 blond 3
6 blonde 1
7 brown 18
8 brown, grey 1
9 grey 1
10 none 38
11 white 4
A esa tabla de frecuencias podemos añadirle la frecuencia relativa calculada como cada frecuencia absoluta dividida por el total (la suma de todos)
tabla_freq <-
tabla_freq |>
mutate("frec_rel" = frec_abs / sum(frec_abs))
tabla_freq# A tibble: 11 × 3
hair_color frec_abs frec_rel
<chr> <int> <dbl>
1 auburn 1 0.0122
2 auburn, grey 1 0.0122
3 auburn, white 1 0.0122
4 black 13 0.159
5 blond 3 0.0366
6 blonde 1 0.0122
7 brown 18 0.220
8 brown, grey 1 0.0122
9 grey 1 0.0122
10 none 38 0.463
11 white 4 0.0488
Este proceso podemos obtenerlo de forma más sencilla con R base (recuerda: funciones aplican a vectores aislados, que debes sacar de la tabla con $ y sin tuberías) con la función table()
tabla_freq <-
table(starwars$hair_color)
tabla_freq
auburn auburn, grey auburn, white black blond
1 1 1 13 3
blonde brown brown, grey grey none
1 18 1 1 38
white
4
También podemos obtener en R base las frecuencias realtivas aplicando prop.table() a la tabla de frecuencias anterior.
prop.table(tabla_freq)
auburn auburn, grey auburn, white black blond
0.01219512 0.01219512 0.01219512 0.15853659 0.03658537
blonde brown brown, grey grey none
0.01219512 0.21951220 0.01219512 0.01219512 0.46341463
white
0.04878049
Moraleja: no te cases de manera acérrima con una forma de hacer las cosas, ambos mundos van a ser necesarios.
Imagina que queremos añadir una columna nueva llamada rol tal que a cada persona le asignamos de manera aleatoria "bueno" (con probabilidad 0.45), "malo" (con probabilidad 0.35), "villano" (con probabilidad 0.2)
Para generar experimentos aleatorios de una variable cualitativa contamos con sample(x = ..., size = ..., replace = ..., probs = ...):
x = c("cruz", "cara"): las opciones que permitimos que salgan.size = 20: las veces que «tiramos la moneda».replace = TRUE: si permitimos reemplazamiento (pueden salir elementos repetidos) o no (en este caso solo podríamos tirar 2 veces).prob = c(0.3, 0.7): las probabilidades de los posibles eventosEn nuestro caso de ejemplo estamos tirando una moneda trucada (más caras que cruces) 20 veces.
sample(x = c("cruz", "cara"), size = 20, replace = TRUE, prob = c(0.3, 0.7)) [1] "cruz" "cruz" "cruz" "cara" "cara" "cruz" "cara" "cruz" "cara" "cruz"
[11] "cara" "cara" "cara" "cara" "cruz" "cara" "cara" "cruz" "cruz" "cruz"
Imagina que queremos añadir una columna nueva llamada rol tal que a cada persona le asignamos de manera aleatoria "bueno" (con probabilidad 0.45), "malo" (con probabilidad 0.35), "villano" (con probabilidad 0.2)
Tendremos que hacer un sample() con las 3 opciones (y sus probabilidades) de tamaño 87 (tenemos 87 personajes).
starwars <-
starwars |>
mutate("rol" = sample(x = c("bueno", "malo", "villano"), size = 87,
replace = TRUE, prob = c(0.45, 0.35, 0.2)),
.after = name)
starwars# A tibble: 87 × 15
name rol height mass hair_color skin_color eye_color birth_year sex
<chr> <chr> <int> <dbl> <chr> <chr> <chr> <dbl> <chr>
1 Luke Sky… vill… 172 77 blond fair blue 19 male
2 C-3PO vill… 167 75 <NA> gold yellow 112 none
3 R2-D2 vill… 96 32 <NA> white, bl… red 33 none
4 Darth Va… bueno 202 136 none white yellow 41.9 male
5 Leia Org… malo 150 49 brown light brown 19 fema…
6 Owen Lars bueno 178 120 brown, gr… light blue 52 male
7 Beru Whi… bueno 165 75 brown light blue 47 fema…
8 R5-D4 bueno 97 32 <NA> white, red red NA none
9 Biggs Da… malo 183 84 black light brown 24 male
10 Obi-Wan … bueno 182 77 auburn, w… fair blue-gray 57 male
# ℹ 77 more rows
# ℹ 6 more variables: gender <chr>, homeworld <chr>, species <chr>,
# films <list>, vehicles <list>, starships <list>
Si te fijas esa variable no solo es cualitativa sino ordinal. Entre las variables cualitativas tenemos nominales (género, sexo, estado civil, etc) y ordinales (estado de salud, rol, etc). ¿Cómo distinguirlas? La forma que tenemos en R de indicarle que una variable de tipo texto (universo informático) es una cualitativa y de qué tipo (universo estadística) es haciendo uso de lo que se conoce como factores
En R las variables cualitativas pueden ser tratadas como tales convirtiendo una cadena de texto a lo que se conoce como factor. Por ejemplo, supongamos que tenemos un vector de notas
notas <- c("suspenso", "notable", "suspenso", "aprobado", "notable", "suspenso")
notas[1] "suspenso" "notable" "suspenso" "aprobado" "notable" "suspenso"
Para convertir a factor nos basta con factor(). ¿Qué notas diferente?
notas_fct <- factor(notas)
notas_fct[1] suspenso notable suspenso aprobado notable suspenso
Levels: aprobado notable suspenso
Si te fijas ahora tenemos disponibles unos niveles (levels): son las posibles modalidades de nuestra variable cualitativa, el soporte, de manera que aunque borremos uno de ellos (vamos a borrar todos los aprobados), la opción sigue disponible si entrase un dato nuevo (algo así como un menú de opciones permitidas)
notas_fct[notas_fct != "aprobado"][1] suspenso notable suspenso notable suspenso
Levels: aprobado notable suspenso
En el caso de las cualitativas ordinales podemos incluso establecer una jerarquía, indicando explícitamente los niveles y ordered = TRUE
notas_fct_ord <- factor(notas, levels = c("aprobado", "notable", "suspenso"),
ordered = TRUE)
notas_fct_ord[1] suspenso notable suspenso aprobado notable suspenso
Levels: aprobado < notable < suspenso
Fíjate que ahora tenemos una jerarquía y aunque sea cualitativa podemos buscar elementos <= o >= que otros
notas_fct_ord[notas_fct_ord <= "notable"][1] notable aprobado notable
Levels: aprobado < notable < suspenso
Volvamos a nuestro ejemplo: ¿cómo convertir nuestra nueva variable rol en una variable cualitativa ordinal (en orden de maldad)? Debemos usar el concepto de factor pero para no aislar la variable de su tabla, lo introduciremos en un mutate()
starwars <-
starwars |>
mutate("rol" = factor(rol, levels = c("bueno", "malo", "villano"),
ordered = TRUE))Cuando tenemos una variable ordinal no solo vamos a poder calcular la tabla de frecuencias absoluta y relativa…
tabla_freq <-
starwars |>
count(rol) |>
mutate("frec_rel" = n/sum(n))
tabla_freq# A tibble: 3 × 3
rol n frec_rel
<ord> <int> <dbl>
1 bueno 40 0.460
2 malo 27 0.310
3 villano 20 0.230
# o bien
table(starwars$rol)
bueno malo villano
40 27 20
…sino que al tener una jerarquía de orden (fíjate que salen automáticamente ordenados) vamos a poder calcular las frecuencias acumuladas con cumsum()
tabla_freq <-
tabla_freq |>
mutate("frec_abs_acum" = cumsum(n),
"frec_rel_acum" = cumsum(frec_rel))
tabla_freq# A tibble: 3 × 5
rol n frec_rel frec_abs_acum frec_rel_acum
<ord> <int> <dbl> <int> <dbl>
1 bueno 40 0.460 40 0.460
2 malo 27 0.310 67 0.770
3 villano 20 0.230 87 1
# o bien
cumsum(table(starwars$rol)) bueno malo villano
40 67 87
cumsum(prop.table(table(starwars$rol))) bueno malo villano
0.4597701 0.7701149 1.0000000
Intenta realizar los siguientes ejercicios sin mirar las soluciones
📝 Para repasar lo aprendido vamos a poner todo en práctica con el dataset SatisfaccionPacientes.csv que tenéis subido al campus. ¿Cómo importarlo?.
library(readr) # dentro de tidyverse
# en mi caso tengo el .csv en una carpeta datos dentro del proyecto
datos <-
read_csv(file = "./datos/SatisfaccionPacientes.csv") |>
# la función clean_names del paquete janitor
# nos normaliza nombres de variables
janitor::clean_names()Rows: 100 Columns: 8
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (3): Genero, EstadoCivil, EstadoSalud
dbl (5): ID, Edad, TiempoEspera, GradoSatisfaccion, NumeroVisitas
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
📝 Aplica el código que sea necesario para responder a estas preguntas. ¿Cuál es el tamaño muestral? ¿Cuántas variables tenemos? ¿Cuántas modalidades tenemos en la variable estado_civil (y cuantas observaciones en cada una)?
# Tamaño muestral / número de observaciones
n <- nrow(datos)
# Número de variables
p <- ncol(datos)
# ¿Qué modalidades tenemos?
datos |>
count(estado_civil)📝 Determina el tipo de variable (cuantitativa vs. cualitativa).
# Variables cuantitativas: tiempo, grado satisfacción, número de visitas
# Variables cualitativas: género, estado civil, estado salud
glimpse(datos)📝 Obten tablas de frecuencias (absoluta y relativa) en el caso de las cualitativas NOMINALES. Con ella intenta responder a las preguntas: a) ¿cuántas mujeres hay? b) ¿qué % de individuos están casados?
# no podemos calcular acumulados ya que genero es nominal
freq_genero <-
datos |>
count(genero) |>
rename(frecuencia_abs = n) |>
mutate(frecuencia_rel = frecuencia_abs/sum(frecuencia_abs))
# Hay 53 mujeres
freq_estado_civil <-
datos |>
count(estado_civil) |>
rename(frecuencia_abs = n) |>
mutate(frecuencia_rel = frecuencia_abs/sum(frecuencia_abs))
# Hay 26% personas casadas📝 Convierte de manera adecuada la variable genero y estado_civil a cualitativa nominal
datos <-
datos |>
mutate(estado_civil = factor(estado_civil),
genero = factor(genero))📝 Calcula la media, mediana, rango intercuartílico y desviación típica de edad y tiempo de espera.
resumen <-
datos |>
summarise(media_edad = mean(edad), sd_edad = sd(edad), mediana_edad = median(edad),
IQR_edad = quantile(edad, probs = 0.75) - quantile(edad, probs = 0.25),
# tiempo espera
media_tiempo_espera = mean(tiempo_espera), sd_tiempo_espera = sd(tiempo_espera),
mediana_tiempo_espera = median(tiempo_espera),
IQR_tiempo_espera = quantile(tiempo_espera, probs = 0.75) - quantile(tiempo_espera, probs = 0.25))📝 Repite el anterior ejercicio pero obteniendo las métricas desagregadas por sexo.
resumen <-
datos |>
summarise(media_edad = mean(edad), sd_edad = sd(edad), mediana_edad = median(edad),
IQR_edad = quantile(edad, probs = 0.75) - quantile(edad, probs = 0.25),
# tiempo espera
media_tiempo_espera = mean(tiempo_espera), sd_tiempo_espera = sd(tiempo_espera),
mediana_tiempo_espera = median(tiempo_espera),
IQR_tiempo_espera = quantile(tiempo_espera, probs = 0.75) - quantile(tiempo_espera, probs = 0.25),
.by = genero)📝 Realiza un gráfico de violín para la variable tiempo_espera para cada género
ggplot(datos) +
geom_violin(aes(x = genero, y = tiempo_espera, fill = genero, color = genero),
alpha = 0.7) +
ggthemes::scale_color_colorblind() +
ggthemes::scale_fill_colorblind() +
theme_minimal()Vamos a seguir poniendo en práctica lo aprendido el dataset SatisfaccionPacientes.csv que tenéis subido al campus, tras haberle normalizado nombres y convertido las variables que tocaban a cualitativas nominales.
library(readr) # dentro de tidyverse
# en mi caso tengo el .csv en una carpeta datos dentro del proyecto
datos <-
read_csv(file = "./datos/SatisfaccionPacientes.csv") |>
# la función clean_names del paquete janitor
# nos normaliza nombres de variables
janitor::clean_names() |>
mutate(estado_civil = factor(estado_civil),
genero = factor(genero))Rows: 100 Columns: 8
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (3): Genero, EstadoCivil, EstadoSalud
dbl (5): ID, Edad, TiempoEspera, GradoSatisfaccion, NumeroVisitas
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
datos# A tibble: 100 × 8
id edad genero estado_civil tiempo_espera grado_satisfaccion
<dbl> <dbl> <fct> <fct> <dbl> <dbl>
1 1 60 Masculino Casado 28 8
2 2 44 Femenino Soltero 22 8
3 3 43 Masculino Soltero 8 9
4 4 32 Masculino Soltero 21 8
5 5 66 Masculino Divorciado 7 10
6 6 43 Masculino Divorciado 20 8
7 7 54 Masculino Casado 18 6
8 8 55 Masculino Soltero 29 6
9 9 56 Masculino Viudo 17 9
10 10 34 Femenino Casado 34 8
# ℹ 90 more rows
# ℹ 2 more variables: numero_visitas <dbl>, estado_salud <chr>
Convierte de manera adecuada la variable
estado_saluda cualitativa ORDINAL
datos <-
datos |>
mutate(estado_salud =
factor(estado_salud, levels = c("Malo", "Regular", "Bueno", "Excelente"),
ordered = TRUE))Haz uso de
table()para calcular la tabla de frecuencias degeneroyestado_civil
table(datos$genero)
table(datos$estado_civil)Calcula la tabla de frecuencias de las ORDINALES y piensa si ahora puedes añadir algo más a la tabla de frecuencias). Tras ello usa el código más sencillo para responder a: ¿cuántas personas tienen un estado de salud regular (o peor)?
freq_estado_salud <-
datos |>
count(estado_salud) |>
rename(frecuencia_abs = n) |>
mutate(frecuencia_rel = frecuencia_abs/sum(frecuencia_abs),
frecuencia_acum_abs = cumsum(frecuencia_abs),
frecuencia_acum_rel = cumsum(frecuencia_rel))
# Se ve dentro de la tabla. Hay 44+15 = 59 personas con un estado de salud malo o regular.
# Con código
datos |>
count(estado_salud <= "Regular")Si te fijas una de las modalidades es totalmente anecdótica (solo 1 Excelente). Sería conveniente recategorizar la categoría Excelente: siempre que detecte Excelente, lo debe recategorizar a Bueno (criterio general: las categorías deben contener al menos un 5% de los individuos de toda la muestra). Pista: mutate e if_else
datos <-
datos |>
mutate(estado_salud = if_else(estado_salud == "Excelente", "Bueno", estado_salud),
# ojo: hay que redefinir los niveles de la cualitativa
# ya que ha dejado de ser factor (veremos un día el paquete forcats para esto)
estado_salud =
factor(estado_salud, levels = c("Malo", "Regular", "Bueno"),
ordered = TRUE))Calcula la media, mediana, rango intercuartílico y desviación típica de grado de satisfacción desagregado por sexo.
resumen <-
datos |>
summarise(media_grado_satisfaccion = mean(grado_satisfaccion),
sd_grado_satisfaccion = sd(grado_satisfaccion),
mediana_grado_satisfaccion = median(grado_satisfaccion),
IQR_grado_satisfaccion =
quantile(grado_satisfaccion, probs = 0.75) -
quantile(grado_satisfaccion, probs = 0.25),
.by = genero)Exporta los resultados anteriores (
resumen) en un archivoresumen.csv. En lugar de unread_csv()vamos a usarwrite_csv(tabla, file = "ruta")
# importado como csv
write_csv(resumen, file = "./resumen.csv")Crear un diagrama de barras para la variable género.
# Género: fíjate que por defecto `geom_bar()` cuenta y visualiza ese conteo `n`.
ggplot(datos) +
geom_bar(aes(x = genero)) ¿Cómo podríamos decirle que cada barra (es decir, para cada modalidad de género) sea de un color (de relleno)?
ggplot(datos) +
# dentro de aes() para que dependa de la tabla
geom_bar(aes(x = genero, fill = genero))En un gráfico no solo podemos usar color como parámetro estético el color sino jugar por ejemplo con la transparencia (parámetro
alpha). Modifica el gráfico anterior para hacer los colores un poco más transparentes.
ggplot(datos) +
geom_bar(aes(x = genero, fill = genero), alpha = 0.75) Una capa muy importante en ggplot es
labs(). Añade títulos a los ejes, leyendas, título de gráfica, subtítulo y pie de figura.
ggplot(datos) +
geom_bar(aes(x = genero, fill = genero), alpha = 0.75) +
labs(title = "Diagrama de barras de la variable género",
subtitle = "Encuesta satisfacción",
caption = "Autor: J. Álvarez y A. Moreno",
x = "Categoría", y = "Frecuencia absoluta", fill = "Categoría")También podemos añadir una capa de tema: unos ajustes (fuente de letra, tamaño, colores de fondo, etc) ya predefinidos. El más “austero” pero cuco es
theme_minimal()
ggplot(datos) +
geom_bar(aes(x = genero, fill = genero), alpha = 0.75) +
labs(title = "Diagrama de barras de la variable género",
x = "Categoría", y = "Frecuencia absoluta",
fill = "Categoría") +
theme_minimal() Tienes más temas en el paquete {ggthemes}
ggplot(datos) +
geom_bar(aes(x = genero, fill = genero), alpha = 0.75) +
labs(title = "Diagrama de barras de la variable género",
x = "Categoría", y = "Frecuencia absoluta",
fill = "Categoría") +
ggthemes::theme_economist()Haz el gráfico anterior pero decidiendo tú qué colores asignas a cada género y con un tema
ggplot(datos) +
geom_bar(aes(x = genero, fill = genero), alpha = 0.75) +
# reminder: el relleno es fill, color para el reborde si quieres
scale_fill_manual(values = c("#379e98", "#eaea3e")) +
labs(title = "Diagrama de barras de la variable género",
x = "Categoría", y = "Frecuencia absoluta",
fill = "Categoría") +
theme_minimal()En el paquete {ggthemes} tienes ya algunas paletas a usar si quieres, por ejemplo para personas daltónicas scale_fill_colorblind()
ggplot(datos) +
geom_bar(aes(x = genero, fill = genero), alpha = 0.75) +
ggthemes::scale_fill_colorblind() +
labs(title = "Diagrama de barras de la variable género",
x = "Categoría", y = "Frecuencia absoluta",
fill = "Categoría") +
theme_minimal()Crear desde cero un diagrama de barras, con ajustes personalizados vistos en los ejercicios anterioes, para la variable estado de salud
# Estado de salud (ahora el orden importa)
ggplot(datos) +
geom_bar(aes(x = estado_salud, fill = estado_salud), alpha = 0.75) +
ggthemes::scale_fill_colorblind() +
labs(title = "Diagrama de barras de la variable estado salud",
x = "Categoría", y = "Frecuencia absoluta",
fill = "Categoría") +
theme_minimal() Fíjate que si no tuviésemos la variable como cuali ordinal, las barras van por orden alfabético, no por jerarquía real
ggplot(datos) +
geom_bar(aes(x = as.character(estado_salud), fill = as.character(estado_salud)),
alpha = 0.75) +
ggthemes::scale_fill_colorblind() +
labs(title = "Diagrama de barras de la variable estado salud",
x = "Categoría", y = "Frecuencia absoluta",
fill = "Categoría") +
theme_minimal() Crea el histograma inferior para las variable edad y tiempo de espera.
ggplot(datos) +
geom_histogram(aes(x = edad), bins = 30, fill = "darkorange", alpha = 0.75) +
labs(title = "Histograma de edad", subtitle = "Bins = 30",
x = "Valores", y = "Frecuencia absoluta") +
theme_minimal()ggplot(datos) +
# Define el ancho de las barras y colores
geom_histogram(aes(x = tiempo_espera), bins = 30, fill = "orchid", alpha = 0.75) +
labs(title = "Histograma de tiempo de espera", subtitle = "Bins = 30",
x = "Valores", y = "Frecuencia absoluta") +
theme_minimal()Crea el gráfico de densidad inferior para las variable edad y tiempo de espera.
ggplot(datos) +
geom_density(aes(x = edad), color = "darkorange",
fill = "darkorange", alpha = 0.75) +
labs(title = "Gráfico de densidad de edad",
x = "Valores", y = "Frecuencia relativa") +
theme_minimal()ggplot(datos) +
geom_density(aes(x = tiempo_espera), color = "orchid",
fill = "orchid", alpha = 0.75) +
labs(title = "Gráfico de densidad de tiempo de espera",
x = "Valores", y = "Frecuencia relativa") +
theme_minimal()Crea el histograma inferior para la variable grado_satisfaccion. ¿Qué opinas?
# Representación regular, no aporta ni resume
ggplot(datos) +
# Define el ancho de las barras y colores
geom_histogram(aes(x = grado_satisfaccion), bins = 30, fill = "#308b8e", alpha = 0.75) +
labs(title = "Histograma de grado de satisfacción", subtitle = "Bins = 30",
x = "Valores", y = "Frecuencia absoluta") +
theme_minimal()# Las **variables discretas muchas veces son mejor representadas** con una diagrama de barrasRealiza un boxplot para edad y un boxplot para numero de visitas PERO por género (dos variables, piensa cómo)
ggplot(datos) +
geom_boxplot(aes(y = edad), fill = "lightblue", alpha = 0.75) +
labs(title = "Boxplot de edad", y = "Edad") +
theme_minimal()ggplot(datos) +
geom_boxplot(aes(x = genero, y = tiempo_espera, fill = genero),
alpha = 0.75) +
labs(title = "Boxplot de tiempo de espera por género",
x = "Género", y = "Tiempo de Espera") +
theme_minimal()Haciendo uso del gráfico anterior:
¿La variable edad tiene outliers? ¿Qué edad tienen esos pacientes?
¿Quién ha esperado más los hombres o las mujeres?
En los boxplots podemos también indicar parámetros concretos para los outliers.
ggplot(datos) +
geom_boxplot(aes(y = edad), fill = "lightblue", alpha = 0.75,
outlier.colour = "red", outlier.shape = 18, outlier.size = 3) +
labs(title = "Boxplot de edad", y = "Edad") +
theme_minimal()Todo lo que hemos hecho con una variable podemos hacerlo también de manera bivariante considerando dos variables. Uno de los principales objetivos de la estadística bivariante es determinar si existe relación o dependencia entre dos variables, es decir, cuando un cambio en el valor de una de ellas se asocia a un cambio en el de la otra (una dependencia estadística no implica un efecto causal). La situación contraria, es decir, la ausencia de relación, se denomina independencia.
Una primera aproximación al estudio de dos variables será clasificar el tipo de análisis
¿Pero que es eso de la inferencia estadística? Es un conjunto de métodos y técnicas que permite inferir conclusiones sobre una población a partir de una muestra de datos.
Su propósito es utilizar la información muestral para estimar características de la población, probar hipótesis y realizar predicciones, basado en el cálculo de estadísticos
Parámetro: medida que describe una característica de la población (ejemplo: la media poblacional \(\mu\) de la estatura de las mujeres en España).
Estadístico: medida que describe una característica de la muestra (ejemplo: la media muestral \(\overline{x}\) de un conjunto de 100 mujeres).
Haciendo uso de estadísticos que aproximen una correcta estimación de los parámetros, los contraste de hipótesis son procedimientos estadísticos para tomar decisiones sobre la validez de una afirmación acerca de una población en función de los datos muestrales.
La idea es muy parecido a un juicio: con las pruebas (muestra) el jurado (estadístico) deben decidir sobre tu culpabilidad real (población), pudiendo ser declarado culpable o no culpable. Este proceso implica formular
Hipótesis nula \(H_0\): es una afirmación generalmente representa una posición de no efecto o no diferencia (ejemplo: entras siendo no culpable a un juicio)
Hipótesis alternativa \(H_0\): es una afirmación que se acepta si se rechaza la hipótesis nula. Representa un efecto o diferencia (ejemplo: culpable)
La idea es similar a la del juicio: solo vamos a rechazar \(H_0\) (es decir, aceptar \(H_1\)) si hay MUCHAS EVIDENCIAS en la muestra (solo se condena culpable a una persona si hay muchas evidencias que demuestran su culpabilidad, pero el acusado no tiene que demostrar su inocencia).
Llamaremos nivel de significancia \(\alpha\) a la probabilidad de rechazar la hipótesis nula cuando es verdadera (condenar a un inocente, conocido como error tipo I. Normalmente \(\alpha = 0.05\) aunque se pueden usar otros valores como 0.01 o 0.10 (a decidir ANTES de realizar el contraste.)
Supongamos que estamos probando si un nuevo medicamento tiene un efecto en la presión arterial \(\mu\)
\[H_0:~\mu = \mu_0~\text{(medicamento no tiene efecto sobre la presión arterial)}\] \[H_1:~\mu \neq \mu_0~\text{(medicamento SI tiene efecto sobre la presión arterial)}\]
donde \(\mu_0\) es la media de la presión arterial antes del tratamiento.
| Decisión | \(H_0\) es cierta | \(H_1\) es cierta |
|---|---|---|
| Se decide rechazar \(H_0\) | Error de tipo I | Acierto |
| Se decide no rechazar \(H_0\) | Acierto | Error de tipo II |
El conocido como p-valor es uno de los conceptos más importantes en estadística pero también peor usados. Puedes ver toda una revisión de qué significa y qué no en https://pmc.ncbi.nlm.nih.gov/articles/PMC4877414/
Podemos definir el p-valor como un valor continuo que nos mide la compatibilidad de los datos observados con el modelo e hipótesis asumidas: 1 indica compatibilidad perfecta y 0 incompatibilidad completa.
No repesenta la probabilidad de que la hipótesis nula sea cierta: el propio p-valor se calcula ASUMIENDO que lo es.
No repesenta la probabilidad de que, por azar, se produzca nada
Una vez visto conceptos básicos de inferencia vamos a empezar por un análisis bivariante de dos variables cualitativas.
El primer paso siempre será intentar resumir la información mediante el uso de tablas de contigencia, en este caso bidimensionales.
¿Cómo lo harías con tidyverse? ¿Y con R base?
Vamos a tomar de nuevo nuestros datos de satisfacción de pacientes
library(readr)
datos <-
read_csv(file = "./datos/SatisfaccionPacientes.csv") |>
janitor::clean_names()Rows: 100 Columns: 8
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (3): Genero, EstadoCivil, EstadoSalud
dbl (5): ID, Edad, TiempoEspera, GradoSatisfaccion, NumeroVisitas
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Para calcular una tabla bidimensional de frecuencias en tidyverse basta con indicar dos variables en count()
datos |>
count(genero, estado_civil)# A tibble: 8 × 3
genero estado_civil n
<chr> <chr> <int>
1 Femenino Casado 11
2 Femenino Divorciado 11
3 Femenino Soltero 22
4 Femenino Viudo 9
5 Masculino Casado 15
6 Masculino Divorciado 8
7 Masculino Soltero 20
8 Masculino Viudo 4
Lo habitual es mostrar esta tabla como una tabla con m filas y n columnas, siendo \(m\) el número de modalidades distintas de la primera variable (en este caso \(m=2\), femenino y masculino) y \(n\) el número de modalidades distintas de la segunda variable (en este caso \(n = 4\)).
¿Cómo hacer que la variable estado_civil pivote para pasar de estar en vertical a estar «en horizontal»? (echa un repaso a la parte de tidy data)
datos |>
count(genero, estado_civil) |>
pivot_wider(names_from = estado_civil, values_from = n)# A tibble: 2 × 5
genero Casado Divorciado Soltero Viudo
<chr> <int> <int> <int> <int>
1 Femenino 11 11 22 9
2 Masculino 15 8 20 4
Esto se puede hacer mucho más sencillo de nuevo en R base con table()
table(datos$genero, datos$estado_civil)
Casado Divorciado Soltero Viudo
Femenino 11 11 22 9
Masculino 15 8 20 4
Fíjate que ahora podemos normalizar las frecuencias de 3 formas: respecto al total de los datos, por filas (margin = 1) o por columnas (margin = 2).
prop.table(table(datos$genero, datos$estado_civil))
Casado Divorciado Soltero Viudo
Femenino 0.11 0.11 0.22 0.09
Masculino 0.15 0.08 0.20 0.04
prop.table(table(datos$genero, datos$estado_civil), margin = 1)
Casado Divorciado Soltero Viudo
Femenino 0.20754717 0.20754717 0.41509434 0.16981132
Masculino 0.31914894 0.17021277 0.42553191 0.08510638
prop.table(table(datos$genero, datos$estado_civil), margin = 2)
Casado Divorciado Soltero Viudo
Femenino 0.4230769 0.5789474 0.5238095 0.6923077
Masculino 0.5769231 0.4210526 0.4761905 0.3076923
Haciendo uso de las tablas anteriores intenta responder a las siguientes preguntas:
¿Qué cantidad de pacientes mujeres están solteras?
¿Qué porcentaje, de entre los pacientes hombres, están viudos?
¿Qué porcentaje, de entre los que están divorciados, son mujeres?
¿Qué porcentaje (del total de pacientes) son hombres solteros?
# a) 22 mujeres
# b) 8.51%
# c) 57.89%
# d) 20%Puedes incluso visualizar dichas cantidades con geom_tile() indicándole que el relleno dependa del conteo n
datos |>
count(genero, estado_civil) |>
ggplot() +
geom_tile(aes(x = genero, y = estado_civil, fill = n)) +
theme_minimal()Esas tablas de frecuencia serán las que usen los diferentes contrastes para decidir si hay o no dependencia entre ellas.
El contraste más conocido es la conocida como prueba de \(\chi^2\) (chi-cuadrado): dada una tabla de contigencia entre dos cualitativas, el contraste compara dicha tabla con la que deberíamos obtener bajo la hipótesis nula de independencia
Vamos a hacerlo con nuestras variables genero y estado_civil
\[H_0:~\text{genero y estado civil son independientes}\]
\[H_1:~\text{genero y estado civil son dependientes}\]
table(datos$genero, datos$estado_civil)
Casado Divorciado Soltero Viudo
Femenino 11 11 22 9
Masculino 15 8 20 4
Si la hipótesis nula fuese cierta, ¿qué esperaríamos?
prop.table(table(datos$genero))
Femenino Masculino
0.53 0.47
table(datos$genero, datos$estado_civil)
Casado Divorciado Soltero Viudo
Femenino 11 11 22 9
Masculino 15 8 20 4
\[E_{ij} = \frac{\text{suma fila i * suma fila j}}{\text{total}}\]
\[\begin{eqnarray}\chi^2 &=& \sum_{i,j} \frac{\left(O_{ij} - E_{ij} \right)^2}{E_{ij}} = \frac{(13.78 - 11)^2}{13.78} + \frac{(12.22 - 15)^2}{12.22} \nonumber \\ &+& \frac{(10.07 - 11)^2}{10.07} + \ldots + \frac{(6.11 - 4)^2}{6.11} = 2.75731\end{eqnarray}\]
Este proceso podemos hacerlo directamente aplicando chisq.test(), indicándole las variables (o su tabla de frecuencias)
contraste <- chisq.test(datos$genero, datos$estado_civil)...$statistic: tenemos guardado el valor del estadísticocontraste$statisticX-squared
2.75731
...$observed: tenemos guardada la tabla de frecuencias observadacontraste$observed datos$estado_civil
datos$genero Casado Divorciado Soltero Viudo
Femenino 11 11 22 9
Masculino 15 8 20 4
...$expected: tenemos guardada la tabla de frecuencias esperadacontraste$expected datos$estado_civil
datos$genero Casado Divorciado Soltero Viudo
Femenino 13.78 10.07 22.26 6.89
Masculino 12.22 8.93 19.74 6.11
...$p.value: tenemos guardado el p-valor.contraste$p.value[1] 0.4305757
¿Cómo interpretar el contraste?
contraste
Pearson's Chi-squared test
data: datos$genero and datos$estado_civil
X-squared = 2.7573, df = 3, p-value = 0.4306
Como \(p.value = 0.4306 > \alpha = 0.05\), no podemos rechazar la hipótesis nula: no hay evidencias suficientes en la muestra para concluir que haya dependencia.
Otra alternativa es el test exacto de Fisher, una prueba estadística utilizada para determinar si hay una asociación significativa entre dos variables cualitativas especialmente útil cuando las frecuencias esperadas son bajas y tenemos dos grupos en cada cualitativa (la tabla de frecuencias es \(2 \times 2\)). No entraremos en mucho detalle matemático pero usa la distribución real de una variable aleatoria que sigue lo que se conoce como distribución hipergeométrica.
Como curiosidad dicha prueba nació cuando Fisher trataba de comprobar si una compañera, Muriel Birstol, era capaz de detectar en un té con leche si se había añadido primero el té o la leche en su taza (y del experiemnto del que nació la regla del \(\alpha = 5%\)).
Para aplicarlo nos basta con usar fisher.test().
fisher.test(datos$genero, datos$estado_civil)
Fisher's Exact Test for Count Data
data: datos$genero and datos$estado_civil
p-value = 0.4462
alternative hypothesis: two.sided
Como hemos dicho es especialmente útil cuando tenemos solo 2 modalidades en cada cualitativa ya nos proporciona métricas de asociación
Veamos un ejemplo con la tabla placebo_medicamento.csv
datos_placebo <- read_csv(file = "./datos/placebo_medicamento.csv")Rows: 33 Columns: 3
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (2): grupo_tratamiento, observado
dbl (1): id_paciente
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
datos_placebo# A tibble: 33 × 3
id_paciente grupo_tratamiento observado
<dbl> <chr> <chr>
1 1 medicamento mejora
2 2 medicamento mejora
3 3 medicamento mejora
4 4 medicamento mejora
5 5 medicamento mejora
6 6 medicamento mejora
7 7 medicamento mejora
8 8 medicamento mejora
9 9 medicamento mejora
10 10 medicamento mejora
# ℹ 23 more rows
fisher.test(datos_placebo$observado, datos_placebo$grupo_tratamiento)
Fisher's Exact Test for Count Data
data: datos_placebo$observado and datos_placebo$grupo_tratamiento
p-value = 0.01336
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
1.308438 57.326435
sample estimates:
odds ratio
7.386906
Si te fijas ahora nos devuelve además un contraste de lo que se conoce como odds ratio (OR: razón de probabilidades)
alternative hypothesis: true odds ratio is not equal to 1
table(datos_placebo$observado, datos_placebo$grupo_tratamiento)
medicamento placebo
mejora 13 6
no mejora 3 11
La interpretación de Odds ratio (OR) es cuantificar la asociación entre dos variables respecto a una asociación espúrea ¿Cuánto mejoran los que tomaron medicamento respecto a una posible mejora basal (aleatoria) del placebo?
\[OR = \frac{13/3}{6/11} = \frac{13*11}{6*3} = 7.94\]
Los pacientes sometidos a tratamiento mejoran 7.9 veces más si el placebo mejorase por azar.
Otra de las métricas habituales es la conocida como razón de prevalencias (Risk Ratio, RR) que nos proporciona un ratio entre la probabilidad de prevalencia de un evento en dos grupos.
\[RR = \frac{13/(3+13)}{6/(11+6)} = \frac{13*11}{6*3} = 2.30208\] Los pacientes sometidos a tratamiento tienen más del doble de «riesgo» de mejorar que los pacientes con placebo.
Ambas métricas podemos estimarlas también con el paquete {epitools}
library(epitools)
OR <- oddsratio(datos_placebo$observado, datos_placebo$grupo_tratamiento)
OR$measure odds ratio with 95% C.I.
Predictor estimate lower upper
mejora 1.000000 NA NA
no mejora 7.201088 1.553915 44.13078
RR <- riskratio(datos_placebo$observado, datos_placebo$grupo_tratamiento)
RR$measure risk ratio with 95% C.I.
Predictor estimate lower upper
mejora 1.000000 NA NA
no mejora 2.488095 1.215737 5.092068
Volvamos al ejemplo de encuesta de satisfacción: vamos a intentar relacionar las dos variables cualitativas genero y estado_civil para complementar el análisis numérico realizado (amén del geom_tile() que hemos hecho para visualizar la tabla de frecuencias)
Sabemos realizar un diagrama de barras de cada una por separado, ¿cómo incluir la información de ambas con geom_bar() Piensa cómo hacerlo recordando que geom_bar() solo admite una coordenada x = ... o y = .... ¿Cómo incluir la info de otra variable que no sea en x o y?
ggplot(datos) +
geom_bar(aes(x = estado_civil, fill = genero), alpha = 0.6) +
ggthemes::scale_fill_colorblind() +
labs(x = "Estado civil", y = "Frec. absolutas",
fill = "Género") +
theme_minimal()
La función geom_bar() nos permite jugar un poco con el tipo de barras, que por defecto las muestra stacked (apiladas). Dicho ajuste podemos cambiarlo con el argumento position: si position = "dodge" las muestra de manera agrupada una detrás de otra.
ggplot(datos) +
geom_bar(aes(x = estado_civil, fill = genero),
position = "dodge", alpha = 0.6) +
ggthemes::scale_fill_colorblind() +
labs(x = "Estado civil", y = "Frec. absolutas",
fill = "Género") +
theme_minimal()La mejor opción para visualizar si hay asociación es que cada barra de estado civil representa el total y nos muestre el % de cada sexo en cada una: si fuesen independientes, el reparto por sexo en cada barra debería ser similar. Lo haremos con position = "fill"
ggplot(datos) +
geom_bar(aes(x = estado_civil, fill = genero),
position = "fill", alpha = 0.6) +
ggthemes::scale_fill_colorblind() +
labs(x = "Estado civil", y = "Frec. relativas",
fill = "Género") +
theme_minimal()ggplot(datos) +
geom_bar(aes(y = estado_civil, fill = genero),
position = "fill", alpha = 0.6) +
ggthemes::scale_fill_colorblind() +
labs(x = "Estado civil", y = "Frec. relativas",
fill = "Género") +
theme_minimal()Intenta realizar los siguientes ejercicios sin mirar las soluciones
📝 Calcula las tablas de frecuencias absoluta y relativa con las variables genero y estado_salud
tabla_freq <- table(datos$genero, datos$estado_salud)
prop.table(tabla_freq)
prop.table(tabla_freq, margin = 1)
prop.table(tabla_freq, margin = 2)📝 Usando la tabla anterior:
¿Qué porcentaje, de entre las mujeres, tiene un buen estado de salud?
¿Qué porcentaje, de entre los hombres, tiene un estado de salud regular?
¿Qué porcentaje de los que tienen estado de salud malo, son mujeres?
# De entre las mujeres un 45.28% tiene un buen estado de salud
# De entre los hombres un 34.04% tiene un estado de salud regular
# Un 33.33% de los que tienen un estado de salud malo, son mujeres📝 Realiza ambos contrastes e intenta razonar la respuesta a la pregunta: ¿están estas dos variables asociadas? ¿Existe algún tipo de dependencia entre ellas? Hazlo considerando \(\alpha = 0.05\).
chisq.test(tabla_freq)$p.value
fisher.test(tabla_freq)$p.value
# En ambos casos p-value > alpha: no podemos rechazar la hipótesis nula de independencia: no hay evidencias suficientes CON LA MUESTRA QUE TENEMOS para concluir que haya alguna asociación📝 Las funciones chisq.test() y fisher.test() proporcionan un objeto htest que dentro contiene el p-valor (accediendo con $p.value dentr de él). ¿Cómo guardar ambos p-valores en una tabla resumen en tidyverse? Exporta los resultados a un .csv
resumen_dependencia <-
datos |>
summarise("sig_chisq" = chisq.test(genero, estado_civil)$p.value,
"sig_fisher" = fisher.test(genero, estado_civil)$p.value)
write_csv(resumen_dependencia, file = "./datos/resumen_dependencia.csv")Carga el fichero
placebo_medicamento_completo.csvdonde tenemos guardado los niveles de colesterol antes y después de un tratamiento: a 76 personas se les dio un medicamento para bajarlo y a 24 personas placebo.
datos <- read_csv(file = "./datos/placebo_medicamento_completo.csv")Rows: 100 Columns: 4
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (1): tratamiento
dbl (3): id, colesterol_pre, colesterol_post
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Añade una nueva variable dicotómica a los datos que nos guarde
mejorasi el paciente mejoró tras el tratamiento yno mejoraen caso negativo
datos <-
datos |>
mutate("mejora" = if_else(colesterol_post <= colesterol_pre, "mejora",
"no mejora"))Visualiza ambas variables (
mejoraytratamiento) a la vez con un diagrama de barras de manera que podamos observar indicios de una posible independencia o dependencia entre ambas. Echa un vistazo a las diapositivas antes. Hazlo antes a papel y boli si lo necesitas
# así pintaríamos en cada barra de tratamiento los mejora o no mejora
ggplot(datos) +
geom_bar(aes(x = tratamiento, fill = mejora), alpha = 0.6) +
ggthemes::scale_fill_colorblind() +
theme_minimal()
# pero dado que tienes más tratados que del grupo control
# no permite comparar bien así que igualamos las barras
# para que cada barra sea el 100% de su categoría
ggplot(datos) +
geom_bar(aes(x = tratamiento, fill = mejora), alpha = 0.6,
position = "fill") +
ggthemes::scale_fill_colorblind() +
theme_minimal()
# Parece evidente visualmente que hay una diferencia entre mejora y no mejora
# en cada barraCalcula la tabla de frecuencias absoluta y relativa que consideres necesarias para responder a las siguientes preguntas:
¿Cuántas personas de las tratadas con medicamento no mejoraron?
¿Qué de personas del total del estudio acabaron mejorando habiendo tomando placebo?
¿Qué % de personas tomó medicamentos entre los que no mejoraron?
¿Qué % de personas de los que tomaron medicamento mejoraron?
table(datos$tratamiento, datos$mejora)
prop.table(table(datos$tratamiento, datos$mejora))
prop.table(table(datos$tratamiento, datos$mejora), margin = 1)
prop.table(table(datos$tratamiento, datos$mejora), margin = 2)
# 9 personas de las tratadas con medicamento no mejoraron
# 9% del total de personas mejoraron y tomaron placebo
# 37% de los que no mejoraron habían tomado la medicación
# 88.1% de los que tomaron medicamento mejoraronPara confirmar y cuantificar las evidencias que ya tenemos, vamos a realizar un contraste de hipótesis. Realiza la prueba de chi-cuadrado e interpreta el resultado con \(\alpha = 0.05\).
chisq.test(datos$tratamiento, datos$mejora)
# Dado que p-value = 1.654e-06 << alpha --> debemos rechazar la hipótesis nula -->
# hay evidencias suficientes para afirmar que hay relación de dependenciaRealiza la prueba de chi-cuadrado y Fisher e incluye los p-valores en una tabla resumen haciendo uso de tidyverse. Exporta a un
.csvdicha tabla resumen
resumen_pvalores <-
datos |>
summarise("sig_chisq" = chisq.test(datos$tratamiento, datos$mejora)$p.value,
"sig_fisher" = fisher.test(datos$tratamiento, datos$mejora)$p.value)
write_csv(resumen_pvalores, file = "./datos/resumen_pvalores.csv")Realiza la prueba de Fisher y mira la salida completa. Interpreta la salida, no solo del contraste sino de los odd ratio.
fisher.test(datos$tratamiento, datos$mejora)
Fisher's Exact Test for Count Data
data: datos$tratamiento and datos$mejora
p-value = 2.519e-06
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
3.722458 42.096028
sample estimates:
odds ratio
11.95213
# OR estimado es de 11.95 --> al ser mayor que 1 implica que
# hay una asociación positiva entre las variables
# hay 12 veces más opciones de que te baje el colesterol si tomas el
# medicamento respecto a una posible mejora aleatoria (porque sí).Carga el archivo de datos fumadores.csv donde tenemos datos de 96 pacientes sobre sí o fuman y quienes han desarrollado o no bronquitis.
datos <- read_csv(file = "./datos/fumadores.csv")Rows: 96 Columns: 3
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (2): fumador, estado
dbl (1): id
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
datos# A tibble: 96 × 3
id fumador estado
<dbl> <chr> <chr>
1 1 sí bronquitis
2 2 sí bronquitis
3 3 sí bronquitis
4 4 sí bronquitis
5 5 sí bronquitis
6 6 sí bronquitis
7 7 sí bronquitis
8 8 sí bronquitis
9 9 sí bronquitis
10 10 sí bronquitis
# ℹ 86 more rows
Realiza la tabla de contigencia de manera absoluta y relativa y responde a las siguientes preguntas
¿Cuántas personas fumaoras tienen bronquitis?
¿Qué % de los fumadores está sano?
¿Qué % del total son a la vez no fumadores y enfermos de bronquitis?
¿Qué % de los enfermos son fumadores?
table(datos$fumador, datos$estado)
prop.table(table(datos$fumador, datos$estado))
prop.table(table(datos$fumador, datos$estado), margin = 1)
prop.table(table(datos$fumador, datos$estado), margin = 2)
# a) 32 personas
# b) 38.46%
# c) 16%
# d) 61.53%Visualiza ambas variables a la vez de manera adecuada que nos permita comparar
ggplot(datos) +
geom_bar(aes(x = fumador, fill = estado), alpha = 0.6, position = "fill") +
labs(x = "fumador", y = "Frec relativa", fill = "Estado") +
theme_minimal()¿Existen evidencias en la muestra de una asociación entre ambas variables?
datos |>
summarise("sig_chisq" = chisq.test(datos$fumador, datos$estado)$p.value,
"sig_fisher" = fisher.test(datos$fumador, datos$estado)$p.value)
# p-valor < alpha --> hay evidencias para rechazar la hip nula
# hay evidencias (no muy fuertes, quizás aumentar tamaño muestral?) de
# que las variables son dependientes y existe una asociaciónSi hubiera asociación, cuantifica la fuerza de dicha asociación (y el sentido) y calcula el riesgo relativo de los fumadores a contraer bronquitis (respecto a no fumadores)
fisher.test(datos$fumador, datos$estado)
# OR estimado = 0.3611 ==> piensa que tenemos no fumar primero y luego fumar ==>
# 1/0.3611 = 2.769316 > 1 ==> hay una asociación positiva entre fumar y tener
# bronquitis
# La bronquitis en pacientes que fuman es 2.77 veces más frecuente
# que en los pacientes que no fuman
# RR ratio
a <- 32 # Expuestos con evento
b <- 16 # Expuestos sin evento
c <- 20 # No expuestos con evento
d <- 28 # No expuestos sin evento
RR <- (a / (a + b)) / (c / (c + d))
# El grupo que fuma tiene un riesgo 1.6 veces mayor de que desarrollar bronquitis en comparación con el grupo que no fuma.Esta la base de datos datos_salud_mental.csv tenemos información recopilada de 100 pacientes que acuden a un centro de salud mental. Se quiere realizar un estudio para ver el impacto que tienen distintas características sobre la ansiedad y depresión en estos 100 pacientes. Los datos incluyen una variedad de variables relacionadas con la salud mental, así como características demográficas y de estilo de vida.
Carga la base de datos y normaliza los nombres de las variables
datos <-
read_csv(file = "./datos/datos_salud_mental.csv") |>
janitor::clean_names()Rows: 100 Columns: 10
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (3): Genero, UsoDrogasRecreativas, TipoDrogas
dbl (7): ID, Edad, Ansiedad, Depresion, SesionesTerapia, ActividadFisica, Ho...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Las variables son:
id: identificador único del paciente.edad: edad del paciente en años.Genero: género del paciente.ansiedad: nivel de ansiedad del paciente en una escala del 1 al 10.depresión: nivel de depresión del paciente en una escala del 1 al 10.sesiones_terapia: número de sesiones de terapia asistidas en el último año.actividad_fisica: número de días a la semana que el paciente realiza actividad física.horas_sueno: número de horas promedio de sueño por noche.uso_drogas_recreativas: indicador de si el paciente ha usado drogas recreativas en el último año.tipo_drogas: tipo de drogas que ha consumido el paciente.¿De qué tipo es cada variable? Convierte las que consideres a cualis nominales y a cualis ordinales, y si hay alguna variable que deba ser lógica
# id: en realidad esto tendría ser un factor (un texto) ya que no cuenta nada
# Cuantitativas: edad, horas_sueno
# Cualitativas nominales: genero, tipo_drogas
# Cuanitativas discretas: sesiones_terapia y actividad_fisica
# Cuantitativas discretas pero que deberíamos tratarlas como cualis ordinales
# ya que son escalas: ansiedad, depresión
# Binarias (cualis ordinales muy concretas): uso_drogas_recreativas
datos <-
datos |>
mutate("id" = as.character(id),
"genero" = factor(genero), "tipo_drogas" = factor(tipo_drogas),
"ansiedad" = factor(ansiedad, levels = as.character(1:10), ordered = TRUE),
"depresion" = factor(depresion, levels = as.character(1:10), ordered = TRUE),
"uso_drogas_recreativas" = (uso_drogas_recreativas == "Si"))Calcula la tabla de frecuencias absolutas y relativas de género.
tabla_freq_abs <- table(datos$genero)
tabla_freq_rel <- prop.table(tabla_freq_abs)Calcula la media de las 4 variables cuantitativas que tenemos desagregado por género. Exporta dicho resumen en un
.csv
resumen <-
datos |>
drop_na(where(is.numeric)) |>
summarise(across(where(is.numeric), mean), .by = genero)
write_csv(resumen, file = "./datos/resumen.csv")Calcula la tabla de contigencia de las variables ansiedad vs genero. Calcula otra para ansiedad vs depresion. Usa
useNA = "always"como argumento para incluir losNA
tabla_freq_genero_ansiedad <- table(datos$genero, datos$ansiedad, useNA = "always")
tabla_freq_depresion_ansiedad <- table(datos$depresion, datos$ansiedad, useNA = "always")Realiza un gráfico adecuado para la variable
edad. Piensa como adaptarlo para tenerlo desagregado porgenero.
# Densidades
ggplot(datos) +
geom_density(aes(x = edad), fill = "#459191", alpha = 0.4) +
labs(x = "Edad (años)", y = "Densidad (frec relativa)") +
theme_minimal()
library(ggridges)
ggplot(datos) +
geom_density_ridges(aes(x = edad, y = genero, fill = genero), alpha = 0.4) +
ggthemes::scale_fill_colorblind() +
labs(x = "Edad (años)", y = "Sexo", fill = "Género") +
theme_minimal()
# Histograma (mala idea con pocos datos)
ggplot(datos) +
geom_histogram(aes(x = edad), bins = 15, fill = "#459191", alpha = 0.4) +
labs(x = "Edad (años)", y = "Frec absoluta") +
theme_minimal()
ggplot(datos) +
geom_histogram(aes(x = edad, fill = genero), bins = 15, alpha = 0.25) +
labs(x = "Edad (años)", y = "Frec absoluta") +
theme_minimal()
# Boxplot
ggplot(datos) +
geom_boxplot(aes(y = edad), fill = "#459191", alpha = 0.4,
outlier.size = 3, outlier.alpha = 0.9,
outlier.color = "#991293", outlier.shape = 18) +
labs(y = "Edad") +
theme_minimal()
ggplot(datos, aes(x = genero, y = edad, fill = genero, color = genero)) +
geom_boxplot(alpha = 0.4, outlier.size = 3, outlier.alpha = 0.9,
outlier.color = "#991293", outlier.shape = 18) +
ggthemes::scale_color_colorblind() +
ggthemes::scale_fill_colorblind() +
guides(color = "none") +
labs(x = "Género", y = "Edad", fill = "Género") +
theme_minimal()Intenta programar el código que necesitarías para obtener los tres gráfico inferiores. Intenta imitarlos al máximo.
ggplot(datos) +
geom_bar(aes(y = ansiedad), fill = "#991293", alpha = 0.5) +
labs(x = "Frecuencia absoluta", y = "Ansiedad (escala 1 a 10)") +
theme_minimal()ggplot(datos) +
geom_bar(aes(y = ansiedad, fill = genero), alpha = 0.5) +
ggthemes::scale_fill_colorblind() +
labs(x = "Frecuencia absoluta", y = "Ansiedad (escala 1 a 10)",
fill = "Género") +
theme_minimal()ggplot(datos) +
geom_bar(aes(y = ansiedad, fill = genero), alpha = 0.5, position = "fill") +
ggthemes::scale_fill_colorblind() +
labs(x = "Frecuencia relativa", y = "Ansiedad (escala 1 a 10)",
fill = "Género") +
theme_minimal()Realiza un gráfico adecuado para visualizar a la vez depresión y ansiedad.
# fíjate que aunque sean números, dado que son variables discretas
# de una escala, no permite una correcta visualización un diagrama
# de dispersión ya que hay muchos puntos iguales que se solapan
ggplot(datos) +
geom_point(aes(x = depresion, y = ansiedad)) +
theme_minimal()
# una opción: se ve un patrón (tipo "recta ascedente")
ggplot(datos |> count(depresion, ansiedad)) +
geom_point(aes(x = depresion, y = ansiedad, color = n, size = n)) +
scale_color_viridis_c() +
guides(size = "none") +
theme_minimal()¿Existe asociación entre genero y uso de drogas? ¿Y entre depresión y ansiedad? Cuantifica la respuesta todo lo que puedas.
resumen_p_valores_1 <-
datos |>
summarise("sig_chisq" = chisq.test(datos$genero, datos$uso_drogas_recreativas)$p.value,
"sig_fisher" = fisher.test(datos$genero, datos$uso_drogas_recreativas)$p.value)Warning: There was 1 warning in `summarise()`.
ℹ In argument: `sig_chisq = chisq.test(datos$genero,
datos$uso_drogas_recreativas)$p.value`.
Caused by warning in `chisq.test()`:
! Chi-squared approximation may be incorrect
# p-valores >> alpha --> no evidencias para rechazar la independencia -->
# no hay evidencias para afirmar la dependencia
# con tantas categorías Fisher no funciona
chisq.test(datos$depresion, datos$ansiedad)Warning in chisq.test(datos$depresion, datos$ansiedad): Chi-squared
approximation may be incorrect
Pearson's Chi-squared test
data: datos$depresion and datos$ansiedad
X-squared = 174.39, df = 63, p-value = 2.148e-12
# p-valores << alpha --> sí hay evidencias para rechazar la independencia -->
# sí hay evidencias para afirmar la dependencia