De acuerdo con lo expuesto en el apartado anterior, para conocer la relación entre dos variables cualitativas (nominales u ordinales) se pueden utilizar:
Tablas de contingencia.
Gráficos.
Pruebas de asociación, por ejemplo, la prueba de \(\chi^2\).
Supongamos que queremos analizar las preferencias políticas en una región en la que existen 3 opciones políticas diferentes. Sospechamos que existe una diferencia acusada entre el ámbito urbano y el ámbito rural. El objetivo es determinar si esa hipótesis es verdad. Para ello, primero crearemos los datos de partida.
<- matrix(c(1200, 900, 400, 680, 250, 650), ncol=3, byrow=TRUE)
datos colnames(datos) <- c("P1","P2","P3")
rownames(datos) <- c("Rural","Urbano")
El análisis de dos variables cualitativas se realiza sobre una tabla
de frecuencias, que es creada a continuación. Otra opción sería utilizar
la función table()
aplicada a un dataframe en el que
contamos con dos variables cualitativas, como se realizó en el tema
2.
<- as.table(datos) tabla1
Como no volveremos a utlizar los datos originales, los borramos del Global Environment.
rm(datos)
Figura 1: Ejemplo de tabla de contingencia
Las frecuencias relativas, en términos de proporciones (tantos por uno), son:
prop.table(tabla1)
Las cifras en la columna de la derecha y en la fila inferior
(“Total”) reciben el nombre de Frecuencias marginales;
la cifra situada en la esquina inferior derecha es el Gran
total. Para añadir las frecuencias marginales a la tabla de
contingencia, se añade una nueva fila con las sumas de cada columna y
una nueva columna con las sumas de cada fila. Con R, esto se lleva a
cabo con la función addmargins()
cuya sintaxis básica
es:
addmargins(tabla, margin=…, FUN=…)
donde:
tabla es una table.
margin es un argumento puede tomar el valor:
1 si queremos una nueva fila con las marginales de cada columna.
2 si queremos una nueva columna con las marginales de cada fila.
c(1,2), que es el valor por defecto para tablas de contingencia bidimensionales (y por lo tanto no hace falta especificarlo), si queremos las marginales por filas y por columnas.
FUN es la función que se aplica a las filas o columnas para obtener el valor marginal. Por defecto es la suma, que es la función que nos interesa en esta lección, y por tanto tampoco hace falta especificarlo.
El resultado es otro objeto de la clase table
al que se
le han añadido una o varias filas o columnas, que contienen las
frecuencias marginales, tanto absolutas como relativas
addmargins(tabla1) # Frecuencias marginales absolutas
addmargins(prop.table(tabla1)) # Frecuencias marginales relativas
En caso de que necesitásemos únicamente la fila o la columna de
frecuencias marginales, las funciones colSums()
y
rowSums()
crean tablas sólo con la suma por columnas o por
filas, respectivamente.
colSums(tabla1)
rowSums(tabla1)
Para la visualización de las tablas de contingencia es posible utilizar diferentes tipos de gráficos.
La función balloonplot()
(paquete
gplots) dibuja una matriz gráfica donde cada celda
contiene un punto cuyo tamaño refleja la magnitud relativa del
componente correspondiente.
library("gplots")
balloonplot(tabla1,
main ="Relación entre género y uso de móvil", # Título del gráfico
xlab ="género", # Etiqueta del eje X
ylab="procedencia", # Etiqueta del eje Y
label = TRUE, # Dibuja el valor numérico de los componentes de la tabla.
show.margins = TRUE) # Dibuja las frecuencias marginales.
Como ya sabemos, se obtiene cuando se aplica la función
barplot()
a una tabla con dos variables (bidimensional),
con dos posibilidades dependiendo del argumento beside
:
si es “FALSE” barras apiladas.
si “TRUE” barras yuxtapuestas.
OPCION 1: barras apiladas (por defecto)
par(mar = c(5, 5, 4, 11))
barplot(tabla1,
main = "Gráfico de barras apiladas",
sub = "Subtítulo",
xlab = "Etiqueta eje X",
ylab = "Etiqueta eje Y",
col = c("red", "blue"),
axes = TRUE,
ylim = c(0, 2000),
legend.text = rownames(tabla1), # Texto de la leyenda
args.legend = list(x = "topright", inset = c(-0.30, 0))) # Posición de la leyenda
par(mar = c(5, 4, 4, 2))
OPCION 2: barras yuxtapuestas
barplot(tabla1,
main = "Gráfico de barras yuxtapuestas",
sub = "Subtítulo",
ylim = c(0,1500),
xlab = "Etiqueta eje X",
ylab = "Etiqueta eje Y",
axes = TRUE,
beside = TRUE)
Desafío
A partir del dataframe zonas_verdes
muestra la relación
entre las variables obras
y barrio
a partir
de
Un gráfico creado con la función ballplot
.
Un gráfico de barras yuxtapuestas que incorpore un título, una leyenda y las etiquetas de los ejes X e Y.
balloonplot(tabla2,
main ="Relación entre género y uso de móvil",
xlab ="obras",
ylab="barrio",
label = FALSE,
show.margins = FALSE)
barplot(tabla2,
main = "Relación entre género y uso de móvil",
sub = "Subtítulo",
ylim = c(0,20),
xlab = "Barrios",
ylab = "Número de parques",
axes = TRUE,
beside = TRUE,
legend.text = rownames(tabla2),
args.legend = list(x = "topright"))
Es un diagrama que facilita la representación visual de la asociación
entre dos o más variables categóricas. En este caso, cada entrada de la
tabla de frecuencias corresponde a una región rectangular de área
proporcional a su valor, utilizando para ello la función
mosaicplot()
del paquete graphics.
Como argumentos adicionales se incluye:
shade
usado para colorear el gráfico.
Color azul: indica que los valores observados son más elevados que los esperados si estos fueran aleatorios
Color rojo: indica que los valores observados son más bajos que los esperados.
las = 2
dispone verticalmente las
etiquetas.
library("graphics")
mosaicplot(tabla1,
shade = TRUE, las = 1)
Existe otro paquete, denominado vcd, que también
puede ser usado para elaborar un gráfico de mosaico con la función
mosaic()
library("vcd")
Para la elaboración del diagrama de mosaico hay que señalar que la primera variable mencionada en la sintaxis corresponde a las columnas (vertical), mientras que la segunda variable corresponde a las filas (horizontal).
mosaic(genero ~ uso_movil_let,
data = df, rot_labels=c(0,90,0,0))
La información proporcionada por este diagrama puede mejorarse.
mosaic(~genero + uso_movil_let,
data = df,
main = "Título",
shade = TRUE, # Colorea la figura
legend = TRUE) # Muestra una leyenda con los resíduos de Pearson.
La leyenda representada en el gráfico de mosaico muestra cuáles son las celdas más relevantes para los resultados de la prueba de chi-cuadrado. Contiene las mismas gamas de colores que en el caso del paquete graphics.
Color azul: significa que hay más observaciones en esa celda de lo que se esperaría bajo el modelo nulo (independencia).
Color rojo (no aparece en este ejemplo) significa que hay menos observaciones de las esperadas.
Los spineplots son una generalización de los gráficos de barras apilados. Un gráfico de mosaico es un spineplot para dos o más variables.
ATENCIÓN: se requiere una tabla de frecuencias
spineplot(tabla1)
Este gráfico puede ser personalizado, por ejemplo, trasponiendo las variables
spineplot(t(tabla1)) # Trasposición de variables
También puede modificarse el color de los cuadros y el borde de éstos
spineplot(tabla1,
col = c("red", "yellow", "blue"),
border = "darkblue") # Color del borde de las barras
Por defecto, la función spineplot crea un spineplot, pero el
argumento off = 0
crea un espinograma, eliminando la
distancia entre las barras.
spineplot(tabla1, off = 0)
Una vez tabulados los datos y visualizadas las posibles diferencias entre variables, el tercer paso es verificar estadísticamente esas posibles diferentes. Para ello recurrimos a varias pruebas.
Una vez elaborada la tabla, es posible evaluar la significación estadística de la diferencia entre ellas con la prueba \(\chi^2\) de Pearson. Esta prueba tiene varios usos:
Opción 1: Evaluar si hay una asociación significativa entre dos o más variables cualitativas en una tabla de frecuencias.
Opción 2: determinar si un variable categórica sigue una distribución hipotética de valores esperados obtenidos de acuerdo a una hipótesis de proporcionalidad (bondad de ajuste).
En el caso que nos ocupa se utiliza la primera opción, siendo denominada prueba de “contraste de independencia” para tablas de contingencia bidimensionales. Consiste en decidir si las dos variables de la tabla tienen distribuciones independientes, es decir, si la distribución de probabilidades conjunta es igual al producto de las probabilidades marginales. Si la proporción de individuos en cada columna varía entre las diversas filas y viceversa, se dice que existe asociación entre las dos variables. Si no existe asociación se dice que ambas variables son independientes.
En nuestro ejemplo, queremos decidir si podemos aceptar que las variables garaje y terraza son independientes o si por el contrario hay evidencia de que la posibilidad de disponer de un garaje depende de la presencia o no de terraza (y esto podría atribuirse a la calidad de la vivienda).
La prueba de \(\chi^2\) presenta algunas características singulares:
Test no paramétrico: no requiere el conocimiento de ciertas características de la población de la que se han extraído las muestras.
Las categorías deben ser por lo menos dos y excluyentes (ningún individuo puede estar en más de una categoría a la vez.
Además, requiere varios pasos.
PRIMER PASO: definir las hipótesis nula y alternativa
Hipótesis nula (H0): las dos variables son independientes (no hay relación entre ellas).
Hipótesis alternativa (H1): las dos variables están relacionadas (no son independientes).
Además, debe decidirse el valor alfa. Esto implica decidir qué riesgo se asume para llegar a una conclusión errónea. Normalmente α=0,05 para las pruebas de independencia, es decir, existe un riesgo del 5 % de concluir que las dos variables son independientes, cuando en realidad no lo son. En este caso:
Si el valor-p α>0,05 se acepta la Hipótesis nula (H0): las dos variables son independientes (no hay relación entre ellas).
Si el valor-p α<0,05 se rechaza la hipótesis nula y se acepta Hipótesis alternativa (H1): las dos variables están relacionadas (no son independientes).
SEGUNDO PASO: cálculo de los valores esperados de cada celda de la tabla bajo la hipótesis nula, de acuerdo con la fórmula
Figura 2: Fórmula valores_esperados
Para ello, en R podemos realizar las siguientes operaciones. En primer lugar, extraemos las frecuencias marginales:
<- length(tabla1)
n
<- rowSums(tabla1) # Frecuencias marginales de las filas
frec.mar.fil <- colSums(tabla1) # Frecuencias marginales de las columnas frec.mar.col
El test de independencia usa las frecuencias absolutas esperadas bajo la hipótesis nula de independencia, que se obtienen, para cada celda (i,j), multiplicando la frecuencia marginal de la fila i por la de la columna j y dividiendo por el tamaño de la muestra. En nuestro ejemplo estas frecuencias esperadas son
Figura 3: Cálculo de los valores esperados
Por lo tanto, con R obtenemos esta tabla de frecuencias esperadas de la manera siguiente:
<- frec.mar.fil%*%t(frec.mar.col)/n
frec.esperadas frec.esperadas
Figura 4: Fórmula chi-cuadrado
Una precaución antes de efectuar el test de independencia es
necesario comprobar que las frecuencias esperadas son mayores o iguales
que 5. Si se cumple esta condición se puede calcular de forma directa o
aplicando la función chisq.test
a la tabla de contingencia
con las frecuencias absolutas.
La sintaxis de forma directa es:
<- sum((tabla1-frec.esperadas)^2/frec.esperadas)
chi2.estadistico chi2.estadistico
El p-valor del contraste se calcula así
<- 1-pchisq(chi2.estadistico,df=(dim(tabla1)[1]-1)*(dim(tabla1)[2]-1))
p.valor p.valor
Mediante la función de R
chisq.test(tabla1)
Como el p-valor
es inferior a 0.05, se rechaza la
hipótesis nula y se acepta la alternativa: las variables objeto de
estudio están relacionadas.
La función chisq.test()
ofrece una serie de outputs
adicionales, como son los siguientes
chisq.test(tabla1)$observed # Valores observados
chisq.test(tabla1)$expected # Valores esperados bajo la hipótesis nula
chisq.test(tabla1)$parameter # Grados de libertad
chisq.test(tabla1)$p.value # Probabilidad
qchisq(0.95, # Valor critico de chi-cuadrado, al 95% con 1 grado de libertad
1) # Grados de libertad, calculados a partir de n-1 (numero de categorias menos uno).
En el caso de tablas formadas por 2 filas y 2 columnas, se debe aplicar una corrección de continuidad.
chisq.test(tabla1,
correct=FALSE) # Indicador lógico para aplicar una corrección de continuidad
Si algunas frecuencias absolutas esperadas fueran inferiores a 5, la
aproximación del p-valor por una distribución \(\chi^2\) podría no ser adecuada. En este
caso, al ser las variables cualitativas, no podemos recurrir al
agrupamiento de valores consecutivos, puesto que no tienen orden. Si se
da esta situación, lo mejor es recurrir a simular el p-valor usando el
argumento simulate.p.value=TRUE
.
set.seed(NULL)
chisq.test(tabla1,
correct=FALSE,
simulate.p.value=TRUE, # Calcula los valores de probabilidad mediante una simulación Monte Carlo
B=5000)$p.value # Número de réplicas simuladas y probabilidad
Otra opción en caso de frecuencias menores a 5 en tablas de contingencia formadas por 2 filas y 2 columnas es el test de Fisher.
?fisher.test
La prueba exacta de Fisher utiliza las siguientes hipótesis nula y alternativa:
Hipótesis nula H0: las dos variables son independientes.
Hipótesis alternativa H1: las dos variables no son independientes (existe relación entre ellas).
fisher.test(tabla1)
En la prueba exacta de Fisher, la hipótesis nula es que las dos columnas son independientes (o, de manera equivalente, que la odds ratio -razón de posibilidades- es igual a 1).
Para determinar si las dos columnas son independientes, se utiliza el
p-value
de la prueba. Si el valor es inferior a 0.05, no
rechazamos la hipótesis nula: no tenemos evidencia suficiente para decir
que existe una asociación estadísticamente significativa entre ambas
variables.
fisher.test(tabla1,
simulate.p.value=TRUE,
B=2^3)
Si se desea conocer qué celdas contribuyen más a los valores de la prueba, se calculan los resíduos de Pearson correspondientes a cada celda (residuos estandarizados)
round(chisq.test(tabla1)$residuals, 3)
Finalmente, es posible visualizar estos resíduos: el tamaño del círculo es proporcional a la contribución de cada celda.
library(corrplot)
corrplot(chisq.test(tabla1)$residuals,is.cor = FALSE)
El grado de asociación entre dos variables se puede cuantificar adicionalmente empleando otros coeficientes:
El coeficiente phi es el valor de la chi cuadrado entre el número de observaciones. En general, cuanto más lejos de 0, más fuerte será la relación entre las dos variables.
Un valor próximo a 0 indica independencia entre los factores.
Valores próximos a -1 indica una relación perfectamente negativa entre las dos variables.
Valores próximos a 1 indica una relación perfectamente positiva entre las dos variables.
El coeficiente de contingencia también es una medida de la intensidad de la relación basado en la chi cuadrado y toma valores entre 0 (independencia) y 1 (dependencia).
La V de Cramer es menos susceptible a valores muestrales.
0 implica independencia
1 una relación perfecta entre los factores. Habitualmente valores superiores a 0,30 ya nos están indicando que hay una posible relación entre las variables; un valor de 0.5 o superior ya indicaría una gran relación entre ambas variables.. En este caso tenemos valores muy próximos a 0 en todos los estadísticos que nos ofrece, ambos factores son independientes. Saludos.
library(vcd)
assocstats(tabla1)
Desafío
PRIMER EJERCICIO
alumnos_UC.RData
. Señala qué
variables son cuantativas y qué variables son cualitativas. A partir de
ese dataframe:load("D:/G14_EE_CC_SS_2023/TEMA_2_Estadistica_Descriptiva/alumnos_UC.Rdata")
$genero <- as.factor(df$genero) df
<- table(df$genero, df$uso_movil_let) tabla2
prop.table(tabla2) * 100
addmargins(tabla_nueva, margin = 1)
addmargins(tabla_nueva, margin = 2)
par(mar = c(5, 5, 4, 11))
barplot(tabla_nueva,
main = "Gráfico de barras apiladas",
sub = "Subtítulo",
xlab = "Etiqueta eje X",
ylab = "Etiqueta eje Y",
col = c("red", "blue"),
axes = TRUE,
ylim = c(0, 60),
legend.text = rownames(tabla_nueva), # Texto de la leyenda
args.legend = list(x = "topright", inset = c(-0.30, 0))) # Posición de la leyenda
par(mar = c(5, 4, 4, 2))
chisq.test(tabla_nueva)
SEGUNDO EJERCICIO
zonas_verdes.Rdata
. A partir de ese
dataframe:load("D:/G14_EE_CC_SS_2023/TEMA_2_Estadistica_Descriptiva/zonas_verdes.Rdata")
str(zonas_verdes)
periodo
deberá ser
convertida en factor para su uso posterior.<- within(zonas_verdes,{
zonas_verdes <- NA # Crea la variable grupo, pero vacía
periodo > "1990-01-01"] <- "Nuevos" # Los restantes comandos rellenan esa variable de manera ordenada
periodo[fecha_inauguracion <= "1990-01-01"] <- "Antiguos"})
periodo[fecha_inauguracion
$periodo <- as.ordered(zonas_verdes$periodo)
zonas_verdes$obras <- factor(zonas_verdes$obras,
zonas_verdeslevels = c(0,1),
labels = c("Sin obras", "Con obras"))
<- addmargins(table(zonas_verdes$obras, zonas_verdes$periodo), margin = c(1,2))
tabla_nueva tabla_nueva
mosaicplot(tabla_nueva,
shade = TRUE,
las = 1)
chisq.test(tabla_nueva)
assocstats(tabla_nueva)
ACTIVIDADES DE EVALUACIÓN CONTINUA
El fichero word 03_Actividad_evaluacion_continua_1_2023 contiene una serie de actividades encaminadas a poner en práctica los conocimientos adquiridos. Cada alumnos deberá elaborar un script que contenga los procedimientos necesarios para responder a las cuestiones planteadas, y enviarlo posteriormente al profesor a través de correo electrónico.
Los resultados de esta actividad pueden consultarse en 03_Actividad_evaluacion_continua_1_2023_resuelta