Autor: Álvaro Alonso Fernández
Departamento de Ciencias de la Vida
Universidad de Alcalá (España)


Vamos a realizar una representación gráfica de un histograma de frecuencias. Es una figura muy empleada para analizar como se distribuyen las frecuencias de cada uno de los valores que toma nuestra variable.


1 Objetivo

Queremos realizar un histograma. Es un gráfico adecuado para mostrar las veces que los diferentes valores de una variable cuantitativa se repiten. Es decir, es adecuado por ejemplo para comprobar si nuestros datos siguen una distribución normal o para comprobar que valores son los más frecuentes dentro de una población. Esto sería muy útil para analizar la estructura de edades de una población.

2 Nuestros datos

Cargamos nuestra matriz de datos, que tendrá el siguiente aspecto:

setwd(dir = "F:/R/MARKDOWN-ggplot2/histograma")
datos<-read.table("histograma.csv", sep = ";", header = TRUE, dec = ".")
datos
##    Treatment Var1 Var2
## 1          1   87   49
## 2          1   82   44
## 3          1   45   58
## 4          1   20   45
## 5          1   22   57
## 6          1   23   70
## 7          1   24   35
## 8          1   17   43
## 9          1    2   39
## 10         1    1   34
## 11         2   85   31
## 12         2   51   41
## 13         2   15   66
## 14         2   93   29
## 15         2   18   62
## 16         2   42   59
## 17         2   40   26
## 18         2   83   67
## 19         2   72   65
## 20         2    7   24
## 21         3   89   36
## 22         3   65   65
## 23         3   39   29
## 24         3   38   66
## 25         3   16   49
## 26         3   47   32
## 27         3   11   35
## 28         3   96   30
## 29         3   71   40
## 30         3   49   69
## 31         4   40   46
## 32         4   50   30
## 33         4   52   51
## 34         4   77   59
## 35         4   31   37
## 36         4   46   58
## 37         4   79   21
## 38         4    6   21
## 39         4   40   59
## 40         4   51   20
## 41         5   51   58
## 42         5   70   49
## 43         5   74   47
## 44         5   80   48
## 45         5   93   43
## 46         5   84   38
## 47         5   20   21
## 48         5   87   43
## 49         5   71   23
## 50         5   97   55
str(datos)
## 'data.frame':    50 obs. of  3 variables:
##  $ Treatment: int  1 1 1 1 1 1 1 1 1 1 ...
##  $ Var1     : int  87 82 45 20 22 23 24 17 2 1 ...
##  $ Var2     : int  49 44 58 45 57 70 35 43 39 34 ...

En este caso tenemos dos variables dependientes (Var1 y Var2). Las variables dependientes son cuantitativas, el resto de valores de la matriz de datos no las vamos a utilizar.

3 Histograma con R base

3.1 Histograma sencillo

Vamos a hacer el histograma más sencillo posible, en este caso solamente vamos a representar los valores que toma la Var1. Veamos que aspecto toma nuestro gráfico:

hist(datos$Var1, col = "darkgreen")

Ahora añadimos los valores individuales en el eje x por medio de rug(datos$Var1):

hist(datos$Var1, col = "darkgreen")
rug(datos$Var1)

Podemos decidir el número de columnas (intervalos para contar la frecuencia) que tendrá nuestro histograma:

par(mfrow=c(2,2))
hist(datos$Var1, col = "green", breaks = 10, main="con 10", xlab="Intervalos")
hist(datos$Var1, col = "green", breaks = 30, main="con 30", xlab="Intervalos")
hist(datos$Var1, col = "green", breaks = 60, main="con 60", xlab="Intervalos")
hist(datos$Var1, col = "green", breaks = 100, main="con 100", xlab="Intervalos")

3.2 Comparar dos histogramas

Comparemos las frecuencias de las dos variables, la Var1 y Var2:

par(mfrow=c(1,2))
hist(datos$Var1, col = "darkgreen", main="Variable 1", xlab="Intervalos")
hist(datos$Var2, col = "black", main="Variable 2", xlab="Intervalos")

Pero lo anterior es mejor hacerlo de la siguiente forma:

par(mfrow=c(1,1))
hist(datos$Var1, main = "Dos variables", ylab = "Frecuencia",xlab="Valores de la variable", ylim=c(0,12))
hist(datos$Var2, add = TRUE, col = rgb(1, 0, 0, alpha = 0.5))

Para conseguir esto es necesario por una parte incluir add = TRUE que representa los dos histogramas juntos. Luego hay que indicar el intervalo del eje y con ylim=c(0,12) en este caso se pone 12 que es el valor máximo de frecuencia que tenemos (lo podemos ver en los dos gráficos separados que hemos hecho antes). Luego con col indicamos el color y con alpha el grado de transparencia de la superposición de los dos histogramas, siendo 1 el máximo valor.

3.3 Histograma y curvas de densidad

Se puede optar por una figura con una curva de densidad. Es una figura de Kernel Density Plot. Para ello:

density1 <- density(datos$Var1)
density1
## 
## Call:
##  density.default(x = datos$Var1)
## 
## Data: datos$Var1 (50 obs.);  Bandwidth 'bw' = 11.95
## 
##        x                 y            
##  Min.   :-34.850   Min.   :1.754e-05  
##  1st Qu.:  7.075   1st Qu.:1.259e-03  
##  Median : 49.000   Median :7.685e-03  
##  Mean   : 49.000   Mean   :5.956e-03  
##  3rd Qu.: 90.925   3rd Qu.:9.652e-03  
##  Max.   :132.850   Max.   :1.078e-02
plot(density1)
polygon(density1, col="darkgreen", border="black")

Esto sería algo parecido a una curva de probabilidad en función de una distribución de datos. No es un histograma de los datos brutos que hemos hecho antes.

Podemos añadir lo anterior a nuestro histograma. En este caso optaremos por una curva de distribución normal de la siguiente manera:

hist(datos$Var1, prob = TRUE, main = "Histograma y curva normalidad", ylab = "Densidad")
primera <- seq(min(datos$Var1), max(datos$Var1), length = 40)
segunda <- dnorm(primera, mean = mean(datos$Var1), sd = sd(datos$Var1))
lines(primera, segunda, col = "red", lwd = 2)

Y ahora añadimos una curva de densidad (parecido a lo que se ha hecho antes en una figura aislada). Para ello utilizamos lines:

hist(datos$Var1, freq = FALSE, main = "Densidad", ylab = "Densidad")
lines(density(datos$Var1), lwd = 2, col = 'red')

3.4 Histograma y boxplot

Se puede combinar en el histograma un boxplot con los valores de nuestra variable. Para ello hacemos lo siguiente:

hist(datos$Var1, probability = TRUE, ylab = "", xlab="Valores de la variable", main = "",
     col = rgb(1, 1, 1, alpha = 0.7), axes = FALSE)
axis(1) # Con esto añadimo sel eje horizontal
par(new = TRUE)
boxplot(datos$Var1, horizontal = TRUE, axes = FALSE,
        lwd = 2.5, col = rgb(0, 0, 0, alpha = 0.3))

Ahora pasaremos a hacer los histogramas empleando el paquete ggplot2. Tiene sus ventajas, para determinados gráficos es mucho mejor que R base, pero su lógica es diferente.

4 Histograma con ggplot2

4.1 Histograma sencillo

Utilizamos ggplot2 para dibujar nuestro histograma. La forma más sencilla de hacerlo sería la siguiente:

library(ggplot2)
## Warning: replacing previous import 'lifecycle::last_warnings' by
## 'rlang::last_warnings' when loading 'tibble'
## Warning: replacing previous import 'lifecycle::last_warnings' by
## 'rlang::last_warnings' when loading 'pillar'
ggplot(data.frame(datos$Var1), aes(x = datos$Var1)) + 
       geom_histogram()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

El resultado no es del todo igual a lo que nos había salido con R base, recordad que con R base habíamos obtenido lo siguiente:

hist(datos$Var1, col = "darkgreen")

Simplemente es la forma de calcular el número de barras del histograma, hay un método -que es el de Sturges- que se aplica para ello. Para obtener lo mismo que con R base haremos:

numbarras <- pretty(range(datos$Var1), n = nclass.Sturges(datos$Var1),
                  min.n = 1)

gr1<-ggplot(data.frame(datos$Var1), aes(x = datos$Var1)) + 
      geom_histogram(breaks = numbarras, color = "black", fill = "darkgreen")
gr1

4.2 Histograma y curvas de densidad

Ahora le podemos añadir una curva de densidad a nuestro histograma, para ello añadimos +geom_density():

gr2<-ggplot(data.frame(datos$Var1), aes(x = datos$Var1)) +
       geom_histogram(aes(y = ..density..), breaks = numbarras,
                      color = "black", fill = "darkgreen") +
       geom_density(fill = "black", alpha = 0.25) #con alpha elegimos el grado de transparencia
gr2

4.3 Mejorar fondo

Ahora vamos a cambiar el fondo de nuestra figura. Hay varias opciones theme_classic(), theme_minimal(), theme_light(), etc. Aquí un resumen:



Vamos a ver como quedan nuestras figuras con las seis opciones disponibles. Aplicamos la libreria patchwork que nos permite agrupar las figuras en una sola:

library(patchwork)

grA<- gr2 + theme_classic()+ theme(legend.position = "none")

grB<- gr2 + theme_minimal()+ theme(legend.position = "none")

grC<- gr2 + theme_light()+ theme(legend.position = "none")

grD<- gr2 + theme_dark()+ theme(legend.position = "none")

grE<- gr2 + theme_gray()+ theme(legend.position = "none")

grF<- gr2 + theme_linedraw()+ theme(legend.position = "none")

(grA | grB | grC ) / (grD | grE | grF )

4.4 Dos histogramas en uno

Ahora vamos a combinar dos histogramas en la misma figura. Para poder hacerlo tenemos que:

gr1<-ggplot(data.frame(datos$Var1), aes(x = datos$Var1)) + 
      geom_histogram(breaks = numbarras, color = "black", fill = "darkgreen") + 
  ylim(c(0,12))

gr3<-ggplot(data.frame(datos$Var2), aes(x = datos$Var2)) + 
      geom_histogram(breaks = numbarras, color = "black", fill = "darkred")

gr1+gr3

Es una primera aproximación, pero vamos a intentar juntar los dos histogramas en una única figura. Para ello tenemos que modificar ligeramente nuestros datos. Las dos variables deben ir en la misma columna con un identificador en otra columna. Utilizamos el paquete tidyr de manejo de matrices:

library("tidyr")

datos2 <- gather(datos,
                 key = "Factor",#nombre para la variable resultante de transponer todas las dos columnas Var1 y Var2
                value = "Variables",#variable que estamos agrupando y el nombre que tendrá la nueva columna
                 Var1:Var2)#desde que columna hasta que columna queremos transponer

datos2
##     Treatment Factor Variables
## 1           1   Var1        87
## 2           1   Var1        82
## 3           1   Var1        45
## 4           1   Var1        20
## 5           1   Var1        22
## 6           1   Var1        23
## 7           1   Var1        24
## 8           1   Var1        17
## 9           1   Var1         2
## 10          1   Var1         1
## 11          2   Var1        85
## 12          2   Var1        51
## 13          2   Var1        15
## 14          2   Var1        93
## 15          2   Var1        18
## 16          2   Var1        42
## 17          2   Var1        40
## 18          2   Var1        83
## 19          2   Var1        72
## 20          2   Var1         7
## 21          3   Var1        89
## 22          3   Var1        65
## 23          3   Var1        39
## 24          3   Var1        38
## 25          3   Var1        16
## 26          3   Var1        47
## 27          3   Var1        11
## 28          3   Var1        96
## 29          3   Var1        71
## 30          3   Var1        49
## 31          4   Var1        40
## 32          4   Var1        50
## 33          4   Var1        52
## 34          4   Var1        77
## 35          4   Var1        31
## 36          4   Var1        46
## 37          4   Var1        79
## 38          4   Var1         6
## 39          4   Var1        40
## 40          4   Var1        51
## 41          5   Var1        51
## 42          5   Var1        70
## 43          5   Var1        74
## 44          5   Var1        80
## 45          5   Var1        93
## 46          5   Var1        84
## 47          5   Var1        20
## 48          5   Var1        87
## 49          5   Var1        71
## 50          5   Var1        97
## 51          1   Var2        49
## 52          1   Var2        44
## 53          1   Var2        58
## 54          1   Var2        45
## 55          1   Var2        57
## 56          1   Var2        70
## 57          1   Var2        35
## 58          1   Var2        43
## 59          1   Var2        39
## 60          1   Var2        34
## 61          2   Var2        31
## 62          2   Var2        41
## 63          2   Var2        66
## 64          2   Var2        29
## 65          2   Var2        62
## 66          2   Var2        59
## 67          2   Var2        26
## 68          2   Var2        67
## 69          2   Var2        65
## 70          2   Var2        24
## 71          3   Var2        36
## 72          3   Var2        65
## 73          3   Var2        29
## 74          3   Var2        66
## 75          3   Var2        49
## 76          3   Var2        32
## 77          3   Var2        35
## 78          3   Var2        30
## 79          3   Var2        40
## 80          3   Var2        69
## 81          4   Var2        46
## 82          4   Var2        30
## 83          4   Var2        51
## 84          4   Var2        59
## 85          4   Var2        37
## 86          4   Var2        58
## 87          4   Var2        21
## 88          4   Var2        21
## 89          4   Var2        59
## 90          4   Var2        20
## 91          5   Var2        58
## 92          5   Var2        49
## 93          5   Var2        47
## 94          5   Var2        48
## 95          5   Var2        43
## 96          5   Var2        38
## 97          5   Var2        21
## 98          5   Var2        43
## 99          5   Var2        23
## 100         5   Var2        55

Ahora con nuestros nuevos datos2 vamos a poder realizar el histograma de frecuencias de las dos variables en una misma figura. Para ello haremos lo siguiente:

ggplot(datos2,aes(x=Variables)) +
  geom_histogram(data=subset(datos2,Factor == 'Var1'), breaks = numbarras,
                 color = "black", fill = "darkgreen", alpha = 0.25) +
  geom_histogram(data=subset(datos2,Factor == 'Var2'), breaks = numbarras,
                 color = "black", fill = "darkred", alpha = 0.25)

Y ahora añadimos la curva de densidad de las dos variables juntas:

ggplot(datos2,aes(x=Variables, y = ..density..)) +
  geom_histogram(data=subset(datos2,Factor == 'Var1'), breaks = numbarras,
                 color = "black", fill = "darkgreen", alpha = 0.25) +
         geom_histogram(data=subset(datos2,Factor == 'Var2'), breaks = numbarras,
                 color = "black", fill = "darkred", alpha = 0.25) +
       geom_density(fill = "black", alpha = 0.15)

4.5 Dos histogramas en uno con mucha información

Para añadir una curva de densidad a cada una de las variables lo que tenemos que hacer es utilizar gghistogram. Como puedes observar es diferente de lo que hemos hecho hasta ahora. Aquí le indicamos que queremos que nos muestre la media add="mean", que divida en función del factor fill="Factor" y que añada las curvas de densidad add_density=TRUE. Veamos el resultado:

library(ggpubr)
## Warning: replacing previous import 'lifecycle::last_warnings' by
## 'rlang::last_warnings' when loading 'hms'
library(cowplot)
## 
## Attaching package: 'cowplot'
## The following object is masked from 'package:ggpubr':
## 
##     get_legend
## The following object is masked from 'package:patchwork':
## 
##     align_plots
gghistogram(
  datos2, x = "Variables", y = "..density..", breaks = numbarras,
  add = "mean", rug = TRUE,
  fill = "Factor", palette = c("darkgreen", "darkred"),
  add_density = TRUE
  )
## Warning: Using `bins = 30` by default. Pick better value with the argument
## `bins`.

Las líneas verticales discontinuas nos muestran la *media de cada una de las variables. También se puede observar una curva de densidad para cada variable. Además, los valores originales aparecen con rayitas a lo largo del eje x. Es una forma muy visual de comprobar como es la distribución de frecuencias de nuestros datos.


Felicidad tras el trabajo bien hecho


5 CRÉDITOS

Álvaro Alonso Fernández

Departamento de Ciencias de la Vida

Universidad de Alcalá (España)