ggplot2 es un sistema para crear gráficos de forma declarativa, basándose en una gramática para gráficos. Su mecánica es la siguiente: le proporcionamos los datos, le decimos cómo asignar variables a la estética, qué tipos de gráficas usar y él se encarga de los detalles. Permite crear gráficos complejos de manera sencilla, aunque también es cierto que puede resultar complejo para hacer gráficos sencillos.

Vamos a utilizar las librerías ggplot2 y ggpubr.

library(ggplot2)
library(ggpubr)

Diagramas de dispersión

Los diagramas de dispersión son útiles para representar dos variables numéricas (tanto discretas como continuas), habitualmente con el objetivo de determinar relaciones o patrones de comportamiento.

Si sólo nos interesa representar el diagrama de dispersión entre dos variables numéricas, bastaría con usar la función de la librería base plot:

# Generamos n valores distribuidos uniformemente entre 1 y 10
n=100
v1=runif(n,0,10)
# Generamos los valores de y como una transformación lineal
# de los valores de x, más una componente aleatoria
v2=3*v1+2+rnorm(n,0,3)
# Regresentamos la nube de puntos
plot(v1,v2)

Para incluir la recta de regresión muestral, que modela su relación, sería necesario estimarla con lm y almacenar su resultado en un objeto para poder utilizarlo:

# Estimamos la recta de regresión muestral y guardamos la salida 
# en el objeto regresion, para poder utilizarla posteriormente
regresion<-lm(v2~v1)
# Representamos el conjunto de datos
plot(v1,v2,pch=21,col="red",bg="gray",cex=2/3,
     main=" ", xlab="x", ylab="y",
     family="Times New Roman" , font=2)
# Añadimos la recta de regresión muestral
abline(regresion)
# Añadimos la expresión de la recta de regresión muestral
text(1.5,30,paste("y = ",round(coef(regresion)[1],2),
     "x +",round(coef(regresion)[2],2)))

Con ggplot2, la construcción del mismo gráfico es más natural. Lo creamos con ggplot pasándole como argumento el nombre del conjunto de datos, dentro de la estética (función aes()) incluímos las variables x e y, seleccionamos geom_point() y añadimos la recta de regresión con geom_smooth(u otra función de suavizado), su expresión con stat_regline_equation() (de la librería ggpubr) y el valor del coeficiente de determinación \(R^2\) con stat_cor(). Además, se pueden usar muchas opciones para personalizar el gráfico como alpha para la transparencia, family y font para el formato del texto, labs para las etiquetas del título, ejes, …

# Creamos un data.frame con las variables v1 y v2
data <- data.frame(x=v1,y=v2)
# Creamos el gráfico
ggplot(data)+
  aes(x=x,y=y)+
  geom_point(alpha=0.75)+
  geom_smooth(formula=y~x, method="lm",se=TRUE,level=0.95)+
  labs(title="Scatter plot",x="x",y="y",family="Times New Roman",font=2)+
  stat_regline_equation(label.x=7.5,label.y=15) +
  stat_cor(aes(label=..rr.label..),label.x=0,label.y=30)

En ocasiones puede interesarnos incorporar otras variables tanto cualitativas como cuantitativas para apreciar relaciones más complejas. Podemos hacerlo utilizándolas para identificar distintos colores o formas (si se trata de factores o variables cualitativas) o tamaño de los puntos (en el caso de que sean numéricas), por ejemplo.

Generamos un nuevo conjunto de datos, con una variable cualitativa con 6 categorías (factor), dos variables cuantitativas continuas (x e y), entre las que habrá distintas relaciones según el valor del factor, y una variable cuantitativa discreta (z).

#Indicamos el número de datos que deseamos generar.
n <- 120
#A continuación, vamos a generar distintas variables numéricas (continuas, discretas), así como variables categóricas. 
v1 <- rep(c("A","B","C","D","E","F"),rep(n/6,6))
v2 <- runif(n,0,10)
v3 <- c(rep(5,20),v2[21:40],-v2[41:60]+10,
        v2[61:80]^2/10,exp(v2[81:100])*10/exp(10),rep(7,20))+rnorm(n)
v4 <- trunc(v2^2)
#Para poder emplear la librería ggplot2 es necesario considerar el conjunto de datos como un data.frame 
data <- data.frame(factor=v1,x=v2,y=v3,z=v4)

Si simplemente representamos las variables numéricas con un diagrama de puntos, no apreciamos ningún patrón de comportamiento:

ggplot(data)+
  geom_point(aes(x=x,y=y))

Sin embargo, si separamos en distintos gráficos según los valores del factor, con la función facet_wrap(), podemos distinguirlos:

ggplot(data)+
  geom_point(aes(x=x,y=y))+
  facet_wrap(vars(factor))

Otra opción sería representarlos en un único gráfico, diferenciando las distintas categorías, por ejemplo por colores:

ggplot(data)+
  geom_point(aes(x=x,y=y,colour=factor))

En este caso no es muy adecuada, pero sí lo sería cuando hay alguna relación entre los distintos patrones de comportamiento. Por ejemplo, lo que ocurre con este otro conjunto de datos:

#Indicamos el número de datos que deseamos generar.
n <- 120
#A continuación, vamos a generar distintas variables numéricas (continuas, discretas), así como variables categóricas. 
v1 <- rep(c("A","B","C","D","E","F"),rep(n/6,6))
v2 <- runif(n,0,10)
v3 <- c(rep(0,20),1/4*v2[21:40],2+1/2*v2[41:60]+1,
        v2[61:80]+2,2*v2[81:100]+3,4*v2[101:120]+4)+rnorm(n)
v4 <- v2^3
#Para poder emplear la librería ggplot2 es necesario considerar el conjunto de datos como un data.frame 
data <- data.frame(factor=v1,x=v2,y=v3,z=v4)
ggplot(data)+
  geom_point(aes(x=x,y=y,colour=factor))

Igual que ocurría con la función básica plot, podemos modificar el tamaño de los puntos, añadir título al gráfico, modificar los ejes (con la función labs), la leyenda (con scale_.._discrete), su posición (con theme()), o el estilo del gráfico (empleando theme_..).

ggplot(data)+
  geom_point(aes(x=x,y=y,colour=factor))+
  labs(title="Diagrama de dispersión",x="x",y="y",family="Times New Roman", font=2)+
  scale_colour_discrete(name="Tipo",labels=c("1","2","3","4","5","6"))+
  theme_minimal()+
  theme(legend.position = "top")

Además del color, también podemos modificar la forma de los puntos en función de alguna variable (con shape)1.

ggplot(data)+
  geom_point(aes(x=x,y=y,shape=factor,colour=factor))+
  labs(title="Diagrama de puntos",x="x",y="y",family="Times New Roman", font=2)+
  theme_classic()+
  theme(legend.position = "left")

También es posible hacer lo mismo con el tamaño de los puntos (size). Esta opción puede ser muy útil cuando queremos dar pesos a nuestros datos (porque no todos son igual de fiables) o simplemente incorporar otra variable numérica sin pasar a 3D.

Además, podemos eliminar leyendas utilizando la función guides(). Para que se puedan diferenciar con claridad los puntos, se puede utilizar alpha = .. en la función geom_point() para indicar la transparencia de los puntos.

ggplot(data)+
  geom_point(aes(x=x,y=y,colour=factor,size=z),alpha=0.5)+
  labs(title="Diagrama de puntos",x="x",y="y",family="Times New Roman", font=2)+
  scale_colour_discrete(name="Factor",labels=c("A","B","C","D","E","F"))+
  guides(size="none")+
  theme_bw()+
  theme(legend.position = "bottom")

Podemos representar la recta de regresión de los subconjuntos según el valor del factor, con la función geom_smooth().

ggplot(data)+
  geom_point(aes(x=x,y=y,colour=factor),alpha=0.75)+
  geom_smooth(aes(x=x,y=y,colour=factor),formula=y~x, method="lm",se=FALSE)+
  labs(title="Diagrama de puntos",x="x",y="y",family="Times New Roman", font=2)+
  scale_colour_discrete(name="Factor",labels=c("A","B","C","D","E","F"))+
  theme_linedraw()

En ambas funciones o capas (geom_point y geom_smooth), la estética es la misma, aes(x=x,y=y,colour=factor), por lo que podemos situarla en una capa (escribiéndola una única vez). Además, es posible añadir otros elementos como el intervalo de confianza al nivel de confianza del 99% (con se=TRUE y level=0.99 en la función geom_smooth()).

ggplot(data)+
  aes(x=x,y=y,colour=factor)+
  geom_point(alpha=0.75)+
  geom_smooth(formula=y~x, method="lm",se=TRUE, level=0.99,)+
  labs(title="Diagrama de puntos",x="x",y="y",family="Times New Roman", font=2)+
  scale_colour_discrete(name="Modelo",labels=c("A","B","C","D","E","F"))+
  stat_regline_equation(label.x=c(0,0,0,0,0,0),
                        label.y=c(40,36,32,28,24,20))+
  theme_light()

Histogramas

Consideremos el conjunto de datos reales sobre la estructura salarial en España en el año 2018. Sus variables son:

# Instala la librería readl, caso de que no esté
if(!"readxl" %in% installed.packages())
  install.packages("readxl")
# Carga la librería
library(readxl)
# Lee el conjunto de datos y lo almacena en el objeto data
data <- read_excel("Salario2018.xlsx")

Si por ejemplo nos interesara comparar la distribución de salarios por sexo, utilizamos la función geom_histogram() con la estética aes(fill=Sexo).

ggplot(data)+
  aes(x=SalarioBase,fill=Sexo)+
  geom_histogram()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Seguramente no se corresponda con el gráfico esperado. Por un lado, representa histogramas apilados; para que aparezcan superpuestos debemos dar el valor identity al argumento position. Por otro lado, tal como nos indica el mensaje, por defecto se representan 30 intervalos que no tiene por qué ser una cantidad adecuada para nuestro conjunto. Se puede modificar dando otro valor a bins (o a center y/o binwidth para completar la personalización de los intervalos eligiendo su centro y anchura, respectivamente) o indicando los puntos de corte en breaks.

ggplot(data)+
  aes(x=SalarioBase,fill=Sexo)+
  geom_histogram(bins=50,alpha=0.75,position="identity")+
  labs(title="Histograma",x="Salario Base",y="")+
  guides(colour="none")+
  theme_bw()+
  geom_freqpoly(binwidth=50,aes(colour=Sexo))

Además hemos añadido el polígono de frecuencias, con geom_freqpoly. Las frecuencias absolutas no suelen ser la mejor opción a efectos comparativos, especialmente cuando los tamaños de las muestras son muy diferentes. En estos casos, resulta más adecuado representar las frecuencias relativas o densidades. Podemos representarlas simplemente añadiendo la estética aes(y=..density..) .

ggplot(data)+
  aes(x=SalarioBase,fill=Sexo)+
  geom_histogram(aes(y=..density..),bins=50,alpha=0.75,position="identity")+
  geom_density()+
  labs(title="Histograma",x="Salario Base",y="")+
  guides(colour="none")+
  theme_minimal()

Para tener una imagen más suave de las frecuencias relativas, y que no dependa de los intervalos utilizados, se utiliza la densidad. Hemos superpuesto las densidades estimadas sobre los histogramas añadiendo la capa geom_density.

Para apreciar más claramente ambas representaciones, hacemos transparente el área de la densidad (con alpha=0) y modificamos el tipo y color de las líneas añadiendo aes(linetype=Sexo,colour=Sexo).

ggplot(data)+
  aes(x=SalarioBase,fill=Sexo)+
  geom_histogram(aes(y=..density..),bins=50,alpha=0.75,position="identity")+
  geom_density(aes(linetype=Sexo,colour=Sexo),alpha=0)+
  labs(title="",x="Salario Base",y="")+
  theme_classic()

Box-plot

Otra forma de comparar distintos subconjuntos es con diagramas de caja y bigotes, que se obtienen con geom_boxplot().

Vamos a cargar otro conjunto de datos, en este caso con extensión Rdata:

load("datosTICr")

Comenzamos representando el diagrama de caja y bigotes para la variable edad, separada por sexo, personalizando su aspecto y añadiendo intervalos de confianza (al 95%)

ggplot(datosTIC)+
  aes(Edad,fill=Sexo)+
  geom_boxplot(colour="gray",outlier.colour = "red", notch = TRUE)

y también por su nivel de confianza en las TICs

ggplot(datosTIC)+
  aes(x=Confianza, y=Edad, colour=Sexo)+
  geom_boxplot(notch = TRUE)

ggplot(datosTIC)+
  aes(x=Sexo, y=Edad, colour=Confianza)+
  geom_boxplot(notch = TRUE)

Cualquiera de los dos gráficos nos permiten apreciar cómo las personas más jóvenes muestran mayor confianza en las TICs, siendo las mayores las que menos responden a la pregunta (valores representados como NA).

Diagramas de violín

De algún modo, combinan las cualidades de los diagramas de caja y bigotes y los histogramas, permitiendo hacer comparaciones de forma muy rápida y sencilla sin prescindir de los detalles. Lo obtenemos con la función geom_violin().

ggplot(datosTIC)+
  aes(x=Sexo,y=Edad, fill=Confianza)+
  geom_violin()+
  labs(title="Diagrama de violín",x="Sexo",y="Edad")+
  theme_bw()

Con las distintas opciones de position podemos cambiar la posición relativa de los distintos “violines”. Por ejemplo, position="identity" los superpone:

ggplot(datosTIC)+
  aes(x=Sexo,y=Edad, fill=Confianza)+
  geom_violin(alpha=0.5,position="identity")+
  labs(title="Diagrama de violín",x="Sexo",y="Edad")+
  theme_bw()

Diagramas de barras

Podemos integrar en ellos la información de varias variables cualitativas o numéricas con pocos valores distintos

ggplot(datosTIC, aes(x=Confianza,fill=UsoInternet))+
  geom_bar(position="identity")

Si nos interesa separar por otra variable, incluimos una capa con facet_wrap.

ggplot(datosTIC, aes(x=Confianza,fill=UsoInternet))+
  geom_bar(position="identity")+
  facet_wrap(~Sexo)

Como ya hemos mencionado, ggplot2 se basa en toda una gramática, por lo que el abanico de posibilidades es tan amplio que solo podremos mostrar algunas de ellas. Recomendamos al lector jugar con las distintas funciones y opciones, asignando otros valores para entender mejor su efecto y probar con otras para comprobar cómo es posible obtener cualquier gráfico que nos imaginemos.


  1. Esta variable no tendría por qué ser la misma.↩︎