Capítulo 4 Estadística descriptiva.
La Estadística Descriptiva es la parte de la Ciencia Estadística que se ocupa de la recopilación de datos, su depuración, y la caracterización mediante dichos datos de un conjunto de casos o individuos.
Los datos se organizan en variables y/o atributos.
Las variables son características de los casos o individuos en estudio que se plasman en valores que están expresados en escala métrica. Los atributos son características de los casos o individuos en estudio que se concretan en diversas categorías (si el atributo tiene escala nominal) o niveles (si el atributo tiene escala ordinal). Los atributos se denominan también variables cualitativas o factores.
Centrándonos en las variables (características que afectan a un grupo de casos o individuos, y que se concretan en valores que poseen una escala métrica), podemos plantearnos el estudio de una única variable sin tener en cuenta la existencia de otras variables que caracterizan al mismo grupo de casos o individuos. En tal caso estaremos planteando un análisis estadístico univariante. Si nuestro análisis se centra en cómo dos variables caracterizan al mismo conjunto de individuos o casos, y la posible relación entre ambas, estaremos planteando un análisis bivariante. Generalizando, si estudiamos cómo un grupo de variables caracterizan de modo conjunto a un mismo grupo de casos o individuos, estaremos planteando un análisis estadístico multivariante.
4.1 Análisis univariante.
En el análisis estadístico univariante, estudiamos cómo una única característica (nos centraremos en una variable, aunque también puede tratarse de un atributo) afecta a un grupo de casos, individuos o elementos. Por ejemplo, la variable podría ser el salario percibido por un grupo de individuos que podría ser el conjunto de trabajadores en nómina en una empresa. Otro ejemplo podría ser el de la (variable) rentabilidad económica obtenida por un grupo de empresas pertenecientes a un determinado sector económico.
El conjunto de pares formado por cada valor que puede tomar la variable en estudio (o categoría o nivel, en el caso de un atributo) y el número de casos que toman tal valor se denomina distribución de frecuencias de la variable.
¿Cómo podemos estudiar el modo en que afecta una variable, de modo global, a un grupo de casos? Mediante el cálculo de una serie de medidas. Las medidas son instrumentos matemáticos que extraen y sintetizan la información contenida en una distribución de frecuencias.
Hay diferentes tipos de medidas, principalmente las de posición, dispersión y forma.
Antes de profundizar en las principales medidas, su significado y su obtención; vamos a indicar cómo se pueden presentar en R, mediante la creación de tablas, los datos referentes a un grupo de individuos y las variables o atributos que los caracterizan, y las distribuciones de frecuencias univariantes.
4.2 Representando datos y distribuciones de frecuencias en tablas con R.
Para aprender a representar los datos referentes a las variables y atributos que caracterizan a un grupo de casos o individuos, y las distribuciones de frecuencias univariantes, vamos a suponer que trabajamos dentro de un proyecto que hemos creado previamente, de nombre “explora”. Dentro de la carpeta del proyecto guardaremos el script llamado “explora_trabajadores.R” y el archivo de Microsoft® Excel® llamado “trabajadores.xlsx”.
Las primeras líneas del script se refieren, como ya hemos visto en otras secciones del libro, a la limpieza de la memoria o environment, eliminando objetos que se hayan podido crear con anterioridad, y en la importación de los datos que hay en la hoja “Datos” de “trabajadores.xlsx”. Estos datos se almacenan en el data frame “datos”, y consisten en el registro del salario (variable SALARIO, expresada en cientos de euros), el nivel de estudios (atributo NESTUDIOS) y departamento al que se pertenece (atributo DEP), correspondientes a los 49 trabajadores de una determinada empresa:
# Script para la construcción de tablas de datos
# y trabajo con distribucionesde frecuencias univariantes.
#
rm(list = ls())
## DATOS
# Importando
library(readxl)
datos <- read_excel("trabajadores.xlsx", sheet = "Datos")
Como sabemos, R interpreta el nombre de los trabajadores como una variable más, en lugar de como la identificador de cada “fila” o caso. Para corregir esto, y hacer saber a R que la primera columna no es una variable, sino el nombre de cada fila (caso, en este caso trabajador), añadimos la línea:
Posteriormente, podremos comprobar que “datos” contiene el valor del salario, el nivel de estudios y la categoría de departamento para cada uno de los 49 trabajadores de la empresa:
## SALARIO NESTUDIOS DEP
## Min. : 8.00 Length:49 Length:49
## 1st Qu.:12.00 Class :character Class :character
## Median :15.00 Mode :character Mode :character
## Mean :16.04
## 3rd Qu.:20.00
## Max. :30.00
Sabemos que, simplemente escribiendo el nombre del data frame, aparecerán en la consola los datos almacenados en él. No obstante, esta presentación no es muy elegante para presentar los datos. Vamos a presentar tales datos de un modo más amigable, mediante la confección de una “tabla”.
Un paquete de R muy popular para generar tablas de datos es {knitr}
.
Este paquete contiene la función kable()
, que permite generar tablas en varios formatos y con diversas características que pueden ser personalizadas (como el título de la tabla).
Si queremos personalizar más aún la apariencia de nuestras tablas, podemos usar las facilidades del paquete {kableExtra}
, que complementa las posibilidades que ofrece la función kable()
de {knitr}
.
Para hacer una tabla con nuestros casos y variables, es decir, para escribir nuestro data frame “datos” de un modo más elegante, primero activaremos los paquetes anteriores, y añadiremos una línea donde diremos el formato de la tabla a generar (en nuestro ejemplo, formato .html), todo con el siguiente código:
Después, generaremos nuestra tabla con los datos contenidos en el data frame “datos”. El código para generar la tabla, y el resultado, es el siguiente:
knitr.table.format = "html"
datos %>%
kable(caption = "Trabajadores asalariados de la empresa",
col.names = c("Trabajador", "Salario", "Nivel de estudios",
"Departamento")) %>%
kable_styling(full_width = F, bootstrap_options = "striped", "bordered",
"condensed", position = "center", font_size = 11) %>%
row_spec(0, bold= T, align = "c") %>%
row_spec(1:(nrow(datos)), bold= F, align = "c")
Trabajador | Salario | Nivel de estudios | Departamento |
---|---|---|---|
Andrés | 8 | Básicos | Almacén |
Ángela | 8 | Medios | Almacén |
Miguel | 9 | Básicos | Almacén |
Luis | 9 | Básicos | Almacén |
María | 9 | Medios | Gestión Interna |
Lourdes | 10 | Medios | Gestión Interna |
Carlos | 10 | Medios | Gestión Interna |
Adriana | 10 | Medios | Gestión Interna |
Ricardo | 10 | Medios | Gestión Proveedores |
Juan José | 10 | Medios | Gestión Proveedores |
Daniel | 10 | Medios | Gestión Proveedores |
Pedro | 12 | Básicos | Almacén |
Ana | 12 | Básicos | Almacén |
Isabel | 12 | Básicos | Almacén |
Manuel | 12 | Medios | Gestión Proveedores |
Isidro | 12 | Medios | Gestión Proveedores |
Carla | 12 | Medios | Gestión Proveedores |
Fernando | 12 | Universitarios | Gestión Clientes |
Belén | 12 | Universitarios | Marketing |
Margarita | 15 | Básicos | Almacén |
Andrea | 15 | Básicos | Almacén |
Pablo | 15 | Medios | Gestión Interna |
Celia | 15 | Medios | Gestión Interna |
Alba | 15 | Medios | Gestión Interna |
Nicolás | 15 | Medios | Gestión Proveedores |
David | 15 | Medios | Gestión Proveedores |
Elena | 15 | Medios | Gestión Proveedores |
Victoria | 15 | Medios | Gestión Proveedores |
Antonio | 15 | Universitarios | Gestión Clientes |
Tomás | 15 | Universitarios | Gestión Clientes |
Bartolomé | 20 | Universitarios | Almacén |
Irene | 20 | Universitarios | Gestión Proveedores |
Guadalupe | 20 | Universitarios | Gestión Proveedores |
Ignacio | 20 | Universitarios | Gestión Proveedores |
Ernesto | 20 | Universitarios | Marketing |
Abel | 20 | Universitarios | Gestión Clientes |
Nieves | 20 | Universitarios | Gestión Clientes |
Carolina | 20 | Universitarios | Gestión Clientes |
Luisa | 22 | Universitarios | Gestión Clientes |
Alberto | 22 | Universitarios | Marketing |
Paula | 22 | Universitarios | Almacén |
Sergio | 22 | Universitarios | Gestión Proveedores |
Estrella | 22 | Universitarios | Gestión Interna |
Alicia | 22 | Universitarios | Coordinación |
Marta | 25 | Universitarios | Dirección |
Alfonso | 25 | Universitarios | Dirección |
Mar | 25 | Universitarios | Dirección |
Martín | 25 | Universitarios | Dirección |
Blanca | 30 | Universitarios | Dirección |
Primero llamamos al data frame a partir de cuyos datos vamos a generar la tabla, “datos”.
Con el operador pipe %>%
, ligamos los datos del data frame al diseño la tabla realizado con la función kable()
de {knitr}
.
kable()
tiene diversos argumentos, entre los que destacan:
caption =
: Este argumento informa del título de la tabla.col.names =
: Este argumento, opcional, fija el nombre para las columnas de la tabla, si no queremos que aparezcan los nombres “por defecto”, que son los nombres de cada columna en el propio data frame.
Luego, con el operador pipe %>%
informamos de que vamos a completar o personalizar el diseño de esta tabla con otras funciones complementarias del paquete {kableExtra}
.
En primer lugar, utilizamos la función kable_styling()
, que aporta algunas características adicionales a la tabla, según sus argumentos:
full_width =
: este argumento ha de tener un valor lógico, y se refiere a si deseamos que la tabla ocupe todo el ancho del documento (TRUE) o solo lo necesario (FALSE).bootstrap_options =
: este argumento es de tipo alfanumérico, y sirve para fijar ciertas características estéticas complementarias. “striped” se refiere a que las filas aparezcan sombreadas de modo alternativo, “bordered” se refiere a que cada fila quede delimitada por unas finas líneas en la parte superior y en la inferior, “condensed” significa que la tabla tendrá un aspecto más compacto.position =
: este argumento se utiliza para situar la tabla centrada, a la izquierda del párrafo, o a la derecha.font_size =
: este argumento numérico se refiere al tamaño de los caracteres, lo cuál es importante a la hora de que una tabla “quepa” en un documento de deteminada anchura.
Por último, hacemos uso dos veces de la función row_spec()
del paquete {kableExtra}
.
Esta función sirve para personalizar algo más las filas concretas de la tabla que consideremos.
El encabezado se identifica como la fila “0”.
En el ejemplo, se ha utilizado esta función dos veces: una para el encabezado (el primer argumento de la función nos informa de las filas a las que se refiere, en esta ocasión la fila 0), y otra para el resto de filas (desde la fila 1 hasta la que contiene al último caso individuo, la fila con posición nrow(datos)
).
Los otros argumentos definen si se quiere que los caracteres aparezcan en negrita (bold =
) y cómo deben estar alineados los elementos, dentro de las columnas ( align =
).
A veces, puede ocurrir que solo nos interese estudiar una variable (columna del data frame). Además, esm posible que el conjunto de casos sea muy numeroso, y que, adicionalmente, algunos de los valores de la variable que queremos estudiar estén repetidos para varios casos. Cuando esto ocurre, una opción interesante es, en lugar de representar en una tabla todos nuestros datos, representar la distribución de frecuencias de la variable (o atributo) que nos interesa. Es lo que vamos a hacer a continuación, tomando como variable a analizar la variable SALARIO.
Lo primero a tener en cuenta es que, en las distribuciones de frecuencias, los valores de la variable suelen disponerse de menor a mayor.
Para ello, previamente vamos a ordenar las filas del data frame “datos” según el valor que toma, en el caso correspondiente, la variable SALARIO y, si existen casos con el mismo valor de SALARIO, los ordenaremos por orden alfabético del nombre del caso (nombre del trabajador, o de la fila del data frame).
Para realizar este reordenamiento de casos (filas) del data frame de un modo sencillo, vamos a utilizar la función arrange()
del paquete {deplyr}
:
Una vez que los casos están ordenados en el data frame de menor a mayor valor de SALARIO, calcularemos, para cada valor del SALARIO, el número de casos que lo poseen, es decir, la frecuencia absoluta de cada valor de la variable SALARIO.
Para ello, vamos a crear un objeto denominado “conteo” que va a ser de clase “tabla” de la variable SALARIO.
Todo ello lo realizamos mediante la función table()
, como se muestra a continuación:
##
## 8 9 10 12 15 20 22 25 30
## 2 3 6 8 11 8 6 4 1
Al mostrar en la consola el objeto “tabla” conteo, vemos cómo se compone de dos filas de datos. La primera se corresponde con los valores que toma la variable SALARIO en los distintos casos, y la segunda es el número de casos (frecuencia absoluta) que toma cada valor. Es decir, el objeto “tabla” es la distribución de frecuencias de la variable SALARIO.
Vamos a convertir este objeto “tabla” en un data frame, llamado “conteo_df”, con el objeto de poder representar de un modo más elegante la distribución de frecuencias. Para ello, ejecutaremos el código:
# Convertir el resultado a un data frame para una mejor visualización
conteo_df <- as.data.frame(conteo)
conteo_df
## Var1 Freq
## 1 8 2
## 2 9 3
## 3 10 6
## 4 12 8
## 5 15 11
## 6 20 8
## 7 22 6
## 8 25 4
## 9 30 1
Al mostrar en la consola el data frame “conteo_df”, observamos que consta de dos columnas o variables. “Var1” recoge los valores que toma la variable SALARIO en el grupo de casos, y “Freq” es el conjunto de frecuencias absolutas de los diferentes valores. Para que se entienda mejor qué es cada columna, las renombraremos:
A continuación, vamos a calcular el resto de frecuencias que suelen calcularse para una variable. La frecuencia total, N, que es la suma de todas las frecuencias absolutas, es decir, el número total de casos, se puede calcular fácilmente como:
La serie de frecuencias absolutas acumuladas se calcularán del siguiente modo:
# Calcular frecuencias absolutas acumuladas
conteo_df$Frecuencia_acum <- cumsum(conteo_df$Frecuencia)
Como sabemos, la última frecuencia absoluta acumulada debe coincidir con la frecuencia total. Por último, calcularemos las frecuencias relativas, que son las frecuencias absolutas divididas por la frecuencia total, y recogen la proporción de casos correspondientes al valor de la variable:
# Calcular frecuencias relativas
conteo_df$Frecuencia_R <- conteo_df$Frecuencia / N
# Calcular frecuencias relativas acumuladas
conteo_df$Frecuencia_R_acum <- cumsum(conteo_df$Frecuencia_R)
La suma de las frecuencias relativas es siempre 1 (el 100% de los casos). Además, la última frecuencia relativa acumulada siempre es, igualmente, 1.
Ahora vamos a construir una tabla que recoja la distribución de frecuencias de la variable SALARIO (con los diversos tipos de frecuencias).
Para ello, simplemente hemos de aplicar al data frame “conteo_df” las funciones kable()
del paquete {knitr}
, y el resto de funciones auxiliares del paquete {kableExtra}
:
conteo_df %>%
kable(caption = "Distribución de frecuencias de los salarios de la empresa",
col.names = c("x(i) = Salario", "Frecuencia absoluta n(i)",
"Frecuencia absoluta acum. N(i)", "Frecuencia relativa f(i)",
"Frecuencia relativa acum. F(i)"),
format.args = list(decimal.mark = ".", digits = 2)) %>%
kable_styling(full_width = F, bootstrap_options = "striped",
"bordered", "condensed",
position = "center", font_size = 11) %>%
row_spec(0, bold= T, align = "c") %>%
row_spec(1:(nrow(conteo_df)), bold= F, align = "c")
x(i) = Salario | Frecuencia absoluta n(i) | Frecuencia absoluta acum. N(i) | Frecuencia relativa f(i) | Frecuencia relativa acum. F(i) |
---|---|---|---|---|
8 | 2 | 2 | 0.04 | 0.04 |
9 | 3 | 5 | 0.06 | 0.10 |
10 | 6 | 11 | 0.12 | 0.22 |
12 | 8 | 19 | 0.16 | 0.39 |
15 | 11 | 30 | 0.22 | 0.61 |
20 | 8 | 38 | 0.16 | 0.78 |
22 | 6 | 44 | 0.12 | 0.90 |
25 | 4 | 48 | 0.08 | 0.98 |
30 | 1 | 49 | 0.02 | 1.00 |
Hemos de advertir que en la función kable()
se ha insertado un nuevo argumento, format.args =
, que es una “lista” que controla aspectos de formato como si los decimales se indican con un punto o una coma, o el número de decimales a mostrar en la tabla.
Hay ocasiones en las que la cantidad de valores diferentes que toma la variable analizada para los diferentes casos es muy elevado. Esto puede deberse, por ejemplo, a que el número de casos es muy elevado, o a que la variable es de naturaleza continua, y puede tomar una gran variedad de posibles valores (incluso infinitos). En estos casos, un modo de representar la distribución de frecuencias de la variable en una tabla de dimensión reducida es agrupando los valores en intervalos. Esto es lo que vamos a hacer ahora con la variable SALARIO.
La primera tarea a realizar será formar los intervalos.
Para ello podemos usar la función cut()
, que permite decir el número de intervalos (de la misma amplitud) en que queremos dividir el intervalo que va desde el menor valor de la distribución (menor salario) al mayor valor (mayor salario).
Por ejemplo, si deseamos agrupar los valores en 4 intervalos, el código será:
# Distribución de frecuencias agrupadas en intervalos
# del salario de los trabajadores de la empresa.
# Crear los intervalos
datos$intervalos <- cut(datos$SALARIO, breaks = 4, include.lowest = TRUE)
El resultado del código anterior es una nueva columna en el data frame “datos”, llamada “intervalos”, que informa, para cada caso, cuál de los 4 intervalos calculados lo contiene.
El argumento lógico include.lowest =
se especifica para indicar que el intervalo inferior es cerrados por la izquierda.
Lo usual es que, salvo este, el resto sean abiertos, es decir, que los casos que toman como valor de la variable un extremo de intervalo se contabilicen dentro del intervalo donde ese valor es el extremo superior.
La columna “intervalos” es de la clase “factor”.
Precisamente, los posibles “niveles” de ese factor son los 4 intervalos que se han creado con cut()
:
## [1] "[7.98,13.5]" "(13.5,19]" "(19,24.5]" "(24.5,30]"
Es preciso advertir que el vector “limites” contiene elementos de clase caracter (aunque contengan cifras, ya que también contienen corchetes, paréntesis y comas).
Las siguientes líneas de código son similares a las que vimos en el caso de distribuciones de frecuencias no agrupadas: se creará un objeto “tabla” para contabilizar el número de casos que pertenecen a cada intervalo (frecuencias absolutas), se transformará este objeto en un data frame para poder trabajar de un modo más fácil, y se cambiarán el nombre de las dos columnas para que se entienda mejor:
# Contar las frecuencias de cada intervalo
conteo_intervalos <- table(datos$intervalos)
# Convertir el resultado a un data frame para una mejor visualización
conteo_intervalos_df <- as.data.frame(conteo_intervalos)
# Renombrar las columnas para mayor claridad
colnames(conteo_intervalos_df) <- c("Intervalo", "Frecuencia")
Con todo lo anterior, se obtiene un data frame denominado “conteo_intervalos_df”, que contiene dos columnas: la columna “Intervalo”, con los 4 intervalos calculados, y la columna “Frecuencia”, con el número de casos que tienen un salario incluido dentro de cada intervalo salarial.
Antes de proceder a diseñar la tabla de presentación de la distribución de frecuencia con kable()
, vamos a obtener, para incluir en la tabla, otras informaciones que suelen ser presentadas junto a las frecuencias absolutas de cada intervalo.
Una de estas informaciones es lo que denominamos “marca de clase” de un intervalo. La marca de clase de un intervalo de valores es simplemente el punto medio de dicho intervalo.
La obtención en nuestro ejemplo de las marcas de clase puede resultar algo compleja, ya que hemos de recordar que los intervalos, tal y como están almacenados, son los niveles de una variable de clase “factor”:
marca_clase <- sapply(strsplit(as.character(conteo_intervalos_df$Intervalo), ",|\\[|\\(|\\]"), function(x) {
mean(as.numeric(x[2:3]))
})
Explicaremos detenidamente el código anterior:
conteo_intervalos_df$Intervalo
: Aquí se está accediendo a la columna “Intervalo” del data frame “conteo_intervalos_df”.as.character(conteo_intervalos_df$Intervalo)
: convierte los valores de la columna “Intervalo” a caracteres (strings). Esto es necesario porque la funciónstrsplit()
trabaja con cadenas de texto.strsplit(as.character(conteo_intervalos_df$Intervalo), ",|\\[|\\(|\\]")
:strsplit()
divide cada cadena de texto en partes usando los delimitadores especificados. En este caso, se están utilizando como delimitadores las comas “,”, los corchetes “[” y ”]”, y el paréntesis de apertura “(”. El resultado es una lista de vectores de caracteres, donde cada vector contiene las partes de la cadena original que estaban separadas por los delimitadores.sapply(..., function(x) { ... })
:sapply()
aplica una función a cada elemento de una lista y simplifica el resultado a un vector o matriz. Por otro lado, la función anónimafunction(x) { ... }
se aplica a cada vector resultante destrsplit()
.function(x) { mean(as.numeric(x[2:3])) }
: Esta es la función anónima que se aplica a cada vector “x”. Después,x[2:3]
selecciona el segundo y tercer elemento del vector “x”. Estos elementos corresponden con los límites del intervalo.as.numeric(x[2:3])
convierte estos elementos a números.mean(as.numeric(x[2:3]))
calcula la media de estos dos números, que representa el punto medio del intervalo.marca_clase <- ...
: Finalmente, el resultado desapply()
se asigna al vector”marca_clase”, que contendrá los puntos medios de los 4 intervalos.
El resto de código integra el vector “marca_clase” en el data frame “conteo_intervalo_df” como una variable más, reodena con la función select() del paquete {dplyr} el orden de las columnas del data frame, calcula el resto de frecuencias (absoluta acumulada, relativa, relativa acumulada), y diseña la tabla de presentación de la distribución de frecuencias de los salarios de los trabajadores de la empresa; pero agrupada en 4 intervalos de valores.
# Agregar la columna "marca_clase" al data frame
conteo_intervalos_df$marca_clase <- marca_clase
#Cambiar el orden de las columnas en el data frame con dplyr
conteo_intervalos_df <- conteo_intervalos_df %>% select(Intervalo, marca_clase, Frecuencia)
# Calcular y guardar la frecuencia total
N_agre <- sum(conteo_intervalos_df$Frecuencia)
# Calcular frecuencias absolutas acumuladas
conteo_intervalos_df$Frecuencia_acum <- cumsum(conteo_intervalos_df$Frecuencia)
# Calcular frecuencias relativas
conteo_intervalos_df$Frecuencia_R <- conteo_intervalos_df$Frecuencia / N_agre
# Calcular frecuencias relativas acumuladas
conteo_intervalos_df$Frecuencia_R_acum <- cumsum(conteo_intervalos_df$Frecuencia_R)
# Mostrar el resultado
conteo_intervalos_df %>%
kable(caption = "Distribución de frecuencias agrupadas en intervalos de los salarios de la empresa",
col.names = c("Intervalo salarial", "Marca de clase x(i)", "Frecuencia absoluta n(i)",
"Frecuencia absoluta acum. N(i)", "Frecuencia relativa f(i)",
"Frecuencia relativa acum. F(i)"),
format.args = list(decimal.mark = ".", digits = 2)) %>%
kable_styling(full_width = F, bootstrap_options = "striped",
"bordered", "condensed",
position = "center", font_size = 11) %>%
row_spec(0, bold= T, align = "c") %>%
row_spec(1:(nrow(conteo_intervalos_df)), bold= F, align = "c")
Intervalo salarial | Marca de clase x(i) | Frecuencia absoluta n(i) | Frecuencia absoluta acum. N(i) | Frecuencia relativa f(i) | Frecuencia relativa acum. F(i) |
---|---|---|---|---|---|
[7.98,13.5] | 11 | 19 | 19 | 0.39 | 0.39 |
(13.5,19] | 16 | 11 | 30 | 0.22 | 0.61 |
(19,24.5] | 22 | 14 | 44 | 0.29 | 0.90 |
(24.5,30] | 27 | 5 | 49 | 0.10 | 1.00 |
4.3 Medidas de posición.
Las medidas de posición son instrumentos matemáticos que pretenden, mediante un único valor o muy pocos valores, caracterizar de modo global la distribución de frecuencias de una variable determinada.
Las medidas de posición se pueden clasificar en medidas de posición central, y en medidas de posición no central (principalmente, los llamados cuantiles).
Las principales medidas de posición central son: la media, la mediana y la moda. Dentro de la media, podemos distinguir la media aritmética, la geométrica y la armónica. De ellas, nos centraremos en la más común: la media aritmética.
La media aritmética de la distribución de frecuencias de una variable X se calcula como:
\[ \overline{x} = \frac{1}{N} \sum_{i=1}^{h} x_i n_i \]
Hemos de tener en cuenta en la fórmula anterior que N es la frecuencia total, y h es el número de valores diferentes que toma la variable.
Si las frecuencias de todos los valores de la variable son 1 (distribución de frecuencias unitarias), lógicamente la media pasará a ser:
\[
\overline{x} = \frac{1}{N} \sum_{i=1}^{N} x_i
\] En R, la función para obtener la media de una variable es mean()
.
Así, para obtener el salario medio de la variable SALARIO de los trabajadoes de la empresa, ejecutaremos el código:
## [1] 16.04082
Como podemos observar, el salario medio de los trabajadores de la empresa, recogido en el valor “media”, es de 16.04 cientos de euros, es decir, 1604 euros.
¿Qué significado tiene la media aritmética? La media aritmética es el “centro de gravedad” de la distribución, el punto de equilibrio, en el sentido de que, si todos los trabajadores ganaran el salario medio, no habría diferencias salariales aun cuando la “masa” salarial invertida por la empresa permanecería invariable. Es decir, la media aritmética supone un reparto igualitario de la masa total de la variable.
Entre sus ventajas destaca el que, para variables (escala métrica) es siempre calculable y única. Como inconvenientes, que pierde su representatividad ante la existencia de casos atípicos o outliers, y que no se puede calcular en el caso de trabajar con atributos, variables cualitativas o factores (escalas nominal u ordinal).
La mediana es el valor que se corresponde con el caso o casos que dividen a la distribución en dos grupos con el mismo número de casos (frecuencias), siempre teniendo en cuenta que, previamente, la distribución ha sido ordenada según los valores de la variable en estudio, de menor a mayor. Si la distribución tiene frecuencia total par, los casos “frontera” entre los dos grupos en que queda dividida la distribución son dos, por lo que, si estos casos asumen valores diferentes en la variable estudiada, podría ocurrir que hubiera dos medianas diferentes. En tal caso, se suele tomar, como convenio, el promedio de de ambos valores para tener una única mediana.
En R, la función para obtener la mediana de una variable es median()
.
De este modo, para obtener el salario mediano de la variable SALARIO de los trabajadoes de la empresa, ejecutaremos el código:
## [1] 15
En el ejemplo de la variable SALARIO, la mediana es 15. Es decir, 15 es el salario percibido por el caso 25, que es el trabajador que divide la distribución de frecuencias en dos grupos de 24 trabajadores: 24 que ganan un salario menor o igual que el caso 25 (menos o igual que 15 cientos de euros), y otros 24 trabajadores que ganan más o lo mismo que el caso en la posición 25 (o sea, más o iagual que 15 cientos de euros).
Como ventaja de la mediana contamos con que no es sensible a la existencia de casos atípicos o outliers, y que se puede calcular en el caso de atributos o factores en escala ordinal. Como desventajas tenemos que no tiene por qué ser única, y que no tiene en cuenta la totalidad de los valores de la distribución.
Con la moda hacemos referencia al valor (o valores) que posee (o poseen) una mayorv frecuencia absoluta.
En R, la moda se calcula mediante la función Mode()
del paquete {DescTools}
, que habremos de activar con library()
(e instalar previamente, si aún no tenemos instalado este paquete):
## [1] 15
## attr(,"freq")
## [1] 11
Como podemos apreciar, la moda de la distribución es 15 (un salario de 1500 euros), que aparece en la distribución en 11 ocasiones (la frecuencia absoluta de ese salario es 11).
La moda puede ser calculada en atributos o factores en escala nominal. Como inconveniente principal tenemos que no tiene por qué ser un valor único (existen distribuciones multimodales).
Existen otras medidas que son de posición no central, principalmente lo que llamamos cuantiles. La naturaleza de loc cuantiles es fácil de comprender si los consideramos una generalización de la mediana. Ya sabemos que, ordenados los valores (y por tanto, los casos que toman dichos valores) de una distribución de frecuencias de una variable de menor a mayor, la mediana es el valor (o valores, porque pueden existir dos medianas, aunque vamos a suponer que solo hay una)) de la variable correspondiente al caso que divide a la distribución en dos grupos con el mismo número de frecuencias. Pues bien, si en lugar de dividir a la distribución de frecuencias en dos grupos con el mismo número de elementos, la dividimos en 4 grupos, estaremos hablando de tres valores correspondientes a los casos que delimitan a esos cuatro grupos. Estos valores serán los cuartiles de la distribución.
Si queremos dividir la distribución de 9 valores de la variable que toman los casos “frontera” que separan a estos 10 grupos. Esos valores serán los deciles. Y si queremos dividir la distribución de frecuencias en 100 grupos con el mismo número de casos o individuos, estaríamos hablando de 99 valores de la variable que toman los casos “frontera” que separan a estos 100 grupos. Esos valores serán los percentiles.
En R, la función para calcular los diferentes cuantiles es quantile()
.
Para calcular, por ejemplo, los cuartiles de la variable SALARIO, procederemos así:
## 25% 50% 75%
## 12 15 20
El argumento probs =
informa de la proporción de los casos que han de quedar por detrás (con valores menores o iguales) de cada uno de los casos que hacen de “frontera” entre los grupos.
En el caso de los cuartiles, estos son 0.25, 0.5 (este cuartil es, a su vez, la mediana de la distribución) y 0.75.
Vemos cómo los cuartiles son 12, 15 y 20.
4.4 Medidas de dispersión o variabilidad.
Las medidas de dispersión cuantifican lo cerca o lejos que, en general, los valores asumidos por los casos de una distribución de frecuencias se hallan respecto a una medida de posición central. Si la medida de dispersión toma un valor muy elevado, querrá decir que la medida de posición central no representa bien a la distribución de frecuencias, ya que, en general, los casos toman valores alejados de dicha medida.
La medida de posición central a la que suelen hacer referencia las medidas de dispersión es la media aritmética.
Existen múltiples medidas de dispersión, que principalmente se dividen en medidas absolutas (que se expresan en ciertas unidades, como por ejemplo euros, o euros al cuadrado) y medidas relativas (que carecen de unidades y siven, por tanto, para comparar la dispersión entre distribuciones de frecuencias expresadas en distintas unidades).
La medida de dispersión absoluta más utilizada es la varianza, cuya fórmula es:
\[ S^2 = \frac{1}{N} \sum_{i=1}^{h} (x_i - \overline{x})^2 n_i \]
Hemos de tener en cuenta en la fórmula anterior que N es la frecuencia total, y h es el número de valores diferentes que toma la variable.
Si las frecuencias de todos los valores de la variable son 1 (distribución de frecuencias unitarias), lógicamente la varianza pasará a ser:
\[ S^2 = \frac{1}{N} \sum_{i=1}^{N} (x_i - \overline{x})^2 \]
En realidad, la varianza es el promedio de las diferencias que existen entre los valores que toma la variable y la media aritmética de esta, diferencias que son elevadas al cuadrado para evitar la compensación entre diferencias por los signos.
Una limitación de la varianza viene referida a que, debido al exponente del paréntesis, puede tomar valores muy elevados. Para evitar el inconveniente, una medida alternativa es la desviación típica, que queda definida como la raíz cuadrada positiva de la varianza:
\[ S = +\sqrt{S^2} \]
Otra media de dispersión muy utilizada, sobre todo en Econometría, es la varianza insesgada o cuasivarianza, cuya fórmula es:
\[ {\overline{S}}^2 = \frac{1}{N-1} \sum_{i=1}^{h} (x_i - \overline{x})^2 n_i \]
Como siempre, si las frecuencias de todos los valores de la variable son 1 (distribución de frecuencias unitarias), lógicamente la cuasivarianza pasará a ser:
\[ {\overline{S}}^2 = \frac{1}{N-1} \sum_{i=1}^{N} (x_i - \overline{x})^2 \]
En cuanto a una medida de dispersión relativa, cabe nombrar al coeficiente de variación de Pearson, definido como el cociente entre la desviación típica y la media aritmética (en valor absoluto):
\[ V = \frac{S}{|\overline{x}|} \]
El coeficiente de variación informa del número de medias aritméticas que “caben” en la desviación típica de una distribución de frecuencias. A mayor coeficiente, mayor dispersión y menor representatividad de la media aritmética con respecto a la distribución. Además, pueden compararse coeficientes de distribuciones expresadas en unidades diferentes (medida relativa).
A continuación, vamos a calcular varianza, desviación típica, cuasivarianza, y coeficiente de variación en R.
Para ello, hemos de tener en cuenta que la función var()
de R, en realidad, calcula la cuasivarianza.
Para obtener la varianza, pues, hemos de realizar una corrección (en realidad, para un número de casos muy grande, ambas medidas prácticamente coinciden):
# Varianza
varianza <- var(datos$SALARIO)*(N-1)/N # recordar que la frecuencia total N ya fue calculada
varianza
## [1] 30.48813
## [1] 5.521606
## [1] 31.1233
## [1] 0.3442222
4.5 Medidas de forma.
Las medidas de forma cuantifican el grado de deformación vertical y horizontal de la representación gráfica de una distribución de frecuencias. Son de dos tipos: medidas de asimetría y medidas de apuntamiento o curtosis.
Las medidas de asimetría miden el grado de deformación vertical con respecto a un “eje de simetría”, que es aquel que pasa por el valor medio de la distribución. Si suponemos que la distribución es unimodal y campaniforme, tendremos los casos que se muestran en la figura:
El tipo y grado de asimetría se puede obtener mediante el coeficiente de asimetría de Fisher.
Este coeficiente toma valor negativo si la distribución es asimétrica negativa (mayores frecuencias a la derecha de la media), valor positivo si la distribución es asimétrica positiva (mayores frecuencias a la izquierda de la media), y se acerca a 0 en caso de que la distribución seaaproximadamente simétrica, aunque pueden darse casos de distribuciones no simétricas con coeficiente 0.
En R, se puede obtener el coeficiente de asimetría mediante la función skewness()
del paquete {moments}
:
# Coeficiente de asimetría de Fisher
library(moments)
asimetria <- skewness(datos$SALARIO)
asimetria
## [1] 0.413764
El valor obtenido para la variable SALARIO de nuestra distribución de frecuencias de los trabajadores de la empresa es positivo, lo que indica asimetría positiva: las mayores frecuencias se localizan a la derecha de la media.
Esto se puede comprobar fácilmente construyendo el histograma de la variable SALARIO y trazando una línea vertical que pase por la media salarial.
Para ello usamos el paquete {ggplot2}
:
library (ggplot2)
ggplot(data = datos, map = aes(x = SALARIO)) +
geom_histogram(bins = 7, colour = "red", fill = "orange") +
geom_vline(aes(xintercept = mean(SALARIO)), colour = "blue", linetype = "dashed", size = 1) +
ggtitle("SALARIO MENSUAL", subtitle = "trabajadores de la empresa XXX")+
xlab("Salario (cientos de euros)") +
ylab("Frecuencias")
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.
Como comprobamos, la distribución es claramente asimétrica positiva.
En cuanto a las medidas de curtosis, miden el grado de deformación horizontal con respecto a una distribución “tipo”, la distribución normal. Suponemos previamente que la distribución de frecuencias estudiada es campaniforme, unimodal y simétrica (o con ligera asimetría). Pueden darse los casos que se muestran en la figura:
El tipo y grado de apuntamiento o curtosis se puede obtener mediante el coeficiente de apuntamiento de Fisher.
Este coeficiente toma valor negativo si la distribución es platicúrtica (más aplastada que la distribución normal), valor positivo si la distribución es leptocúrtica (más apuntada que la distribución normal), y se acerca a 0 en caso de que la distribución sea aproximadamente igual de apuntada que la distribución normal.
En R, se puede obtener el coeficiente de asimetría mediante la función kurtosis()
del paquete {moments}
.
Hay que tener en cuenta que para que esta versión coincida con lo dicho anteriormente, al valor calculado hay que restarle el valor “3”:
## [1] -0.8232965
Se aprecia como el coeficiente (corregido) es menor que 0, por lo que la distribución de frecuencias de la variable SALARIO es platicúrtica (más “aplastada” que la distribución de frecuencias normal. También hay que tener en cuenta que debemos tener precaución en la aplicación del coeficiente, ya que vimos con anterioridad que la distribución no es aproximadamente simétrica. Gráficamente, podemos comprobar lo anterior representando el histograma y una curva normal que posea la misma moda (que ya calculamos anteriormente).
Para que sean comparables, debemos transformar el eje “y” del gráfico, pasando de “frecuencias” a “densidad”, para lo cuál se incluye en el geom_histogram()
el argumento aes(y = ..density..)
:
ggplot(data = datos, map = aes(x = SALARIO)) +
geom_histogram(bins = 7, colour = "red", fill = "orange", aes(y = ..density..)) +
stat_function(fun = dnorm, args = list(mean = moda, sd = sd(datos$SALARIO)), colour = "darkblue", size = 1) +
ggtitle("SALARIO MENSUAL", subtitle = "trabajadores de la empresa XXX")+
xlab("Salario (cientos de euros)") +
ylab("Densidad")
## Warning: The dot-dot notation (`..density..`) was deprecated in ggplot2 3.4.0.
## ℹ Please use `after_stat(density)` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.
4.6 Materiales para realizar las prácticas del capítulo.
En esta sección se muestran los links de acceso a los diferentes materiales (scripts, datos…) necesarios para llevar a cabo los contenidos prácticos del capítulo.
Datos (en formato Microsoft (R) Excel (R)):
- trabajadores.xlsx (obtener aquí)
Scripts:
- explora_trabajadores.R (obtener aquí)