Autor: Álvaro Alonso Fernández
Departamento de Ciencias de la Vida
Universidad de Alcalá (España)
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.
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.
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")
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.
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')
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.
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
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
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 )
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)
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.
Departamento de Ciencias de la Vida
Universidad de Alcalá (España)