1. Introducción.

En R tenemos disponibles distintos sistemas gráficos, aunque los más comunes son:

En esta sesión vamos a aprender a crear gráficos (básicos), puesto que constituyen herramientas enormemente valiosas para transmitir información. “Más vale una imagen que mil palabras”.

Comenzaremos haciendo distintos tipos de gráficos usando el sistema base y después los replicaremos utilizando ggplot2.

2. Gráficos base.

Para realizar los gráficos de este tutorial vamos a utilizar datos que se encuentran accesibles en el paquete AER. Por tanto, cargamos la librería AER (si no la tenemos hay que instalar el paquete).

if(!require("AER")) {install.packages("AER")}
## Loading required package: AER
## Loading required package: car
## Loading required package: carData
## Loading required package: lmtest
## Loading required package: zoo
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
## Loading required package: sandwich
## Loading required package: survival

El paquete AER contiene más de 100 bases de datos (data sets). Veamos las bases de datos que tiene el paquete.

data(package="AER")

La base de datos que utilizaremos para crear las gráficas de este tutorial es CPS1985 (más información aquí). Primero cargamos la librería y luego cargamos la base de datos.

library(AER)
data("CPS1985")

¿Cuántas observaciones hay? ¿Qué variables contiene la base de datos CPS1985?

dim(CPS1985)
## [1] 534  11
names(CPS1985)
##  [1] "wage"       "education"  "experience" "age"        "ethnicity" 
##  [6] "region"     "gender"     "occupation" "sector"     "union"     
## [11] "married"

Así pues, tenemos un total de 554 observaciones y las siguientes 11 variables:

Antes de comenzar con los gráficos, vamos a obtener un resumen de las variables.

summary(CPS1985)
##       wage          education       experience         age       
##  Min.   : 1.000   Min.   : 2.00   Min.   : 0.00   Min.   :18.00  
##  1st Qu.: 5.250   1st Qu.:12.00   1st Qu.: 8.00   1st Qu.:28.00  
##  Median : 7.780   Median :12.00   Median :15.00   Median :35.00  
##  Mean   : 9.024   Mean   :13.02   Mean   :17.82   Mean   :36.83  
##  3rd Qu.:11.250   3rd Qu.:15.00   3rd Qu.:26.00   3rd Qu.:44.00  
##  Max.   :44.500   Max.   :18.00   Max.   :55.00   Max.   :64.00  
##     ethnicity     region       gender         occupation            sector   
##  cauc    :440   south:156   male  :289   worker    :156   manufacturing: 99  
##  hispanic: 27   other:378   female:245   technical :105   construction : 24  
##  other   : 67                            services  : 83   other        :411  
##                                          office    : 97                      
##                                          sales     : 38                      
##                                          management: 55                      
##  union     married  
##  no :438   no :184  
##  yes: 96   yes:350  
##                     
##                     
##                     
## 

En el caso de variables cuantitativas, la función summary() proporciona como resumen de la variable los “cinco números” (mínimo, cuartil 1, cuartil 2, cuartil 3, máximo) y la media. Si el variable es categórica proporciona el total de observaciones en cada categoría.

Histograma.

Vamos a comenzar por representar un (sencillo) histograma del Salario (wage). La función que utilizamos es hist().

hist(CPS1985$wage)

Así queda poco atractivo. ¿Qué podemos hacer para mejorarlo?

Antes que nada, como no vamos a abrir ninguna otra base de datos, para evitar tener que escribir continuamente CPS1985$variable, hacemos un attach. Esto nos permite acceder directamente a las variables de CPS1985 (y nos evitamos escribir mucho).

attach(CPS1985)   # accedemos directamente a las variables (columnas)
p<-hist(wage)
text(p$mids,p$counts,labels=p$counts, adj=c(0.5, -0.5), cex=.5)

Ahora sí, vamos a mejorar el histograma. Pero para ello tenemos que conocer los argumentos de la función hist(). Por tanto, pedimos la ayuda.

?hist()
## starting httpd help server ... done

En primer lugar, para mejorar nuestro histograma, modificamos el número de intervalos (breaks) (se obtiene con la Regla de Sturges. A continuación, escribimos el título del gráfico y rotulamos los ejes.

hist(wage,
     breaks = 20,   # número de intervalos
     main = "Distribución del Salario (dólares por hora)",    # título del gráfico
     xlab = "Salario",                                        # título del eje x
     ylab = "Número de personas"                              # título del eje y
     )

¿Qué más podemos hacer? Por ejemplo, podemos modificar el rango de valores del eje x (y/o del eje y) y colorear el histograma. La paleta de colores que por defecto tiene R se puede consultar ejecutando la función palette(). Para consultar nombres de colores podemos ejecutar en la consola colors() o hacer clic aquí.

hist(wage,
     breaks = 20,   
     main = "Distribución del Salario (dólares por hora)", 
     xlab = "Salario",                                          
     ylab = "Número de personas",
     xlim = c(0,50),                      # rango de valores del eje x
     col = "blue",                        # color de relleno
     border = "white"                     # color del borde del rectángulo
     )

Si en lugar de representar la frecuencia absoluta estamos interesados en representar la frecuencia relativa (probability Density ) tenemos que cambiar el argumento freq de la función hist().

hist(wage,
     breaks = 20,   
     main = "Distribución del Salario (dólares por hora)", 
     freq = FALSE,                  # frecuencias relativas (en tanto por uno)
     xlab = "Salario",                                          
     ylab = "Frecuencia relativa (en tanto por uno)", 
     xlim = c(0,50),
     ylim =c (0,0.15),              # cambiamos rango de valores del eje y 
     col = "purple",
     border = "white"
     )

En ocasiones, por no decir casi siempre, nos gusta añadir al histograma la curva de la distribución normal; vamos a ver cómo hacerlo.

hist(wage,
     breaks = 20,   
     main = "Distribución del Salario (dólares por hora)", 
     freq = FALSE,
     xlab = "Salario",                                          
     ylab = "Frecuencia relativa (en tanto por uno)", 
     xlim = c(0,50),
     ylim = c(0,0.15),
     col = "blue",
     border = "white"
     )

lines(density(wage), col="yellow", lwd=3)  # dibujamos la distribución normal empírica con los  datos que tenemos

lines(density(wage, adjust=2), col="red", lwd=3, lty=2) # adjust=2 lo que hace es suavizar un poco la curva (puedes probar con adjust=1 y adjust=5 para ver las diferencias).

En el gráfico anterior se han utilizado los argumentos lwd y lty. El primero se refiere al grosor de la línea, el segundo al tipo de línea.

La siguiente gráfica sería una alternativa a la anterior.

hist(wage,
     breaks = 20,   
     main = "Distribución del Salario (dólares por hora)", 
     freq = FALSE,
     xlab = "Salario",                                          
     ylab = "Frecuencia relativa (en tanto por uno)", 
     xlim = c(0,50),
     ylim = c(0,0.15),
     col = "blue",
     border = "white"
     )

curve(dnorm(x, mean=mean(wage), sd=sd(wage)), add=TRUE, col="red", lwd=3)  # aquí simulamos valores de una normal con la misma media y deviación típica que wage y la representamos.

En los gráficos anteriores hemos seleccionado el color (muy básico) para el relleno o para el borde escribiendo directamente el nombre (del color). El tema de los colores es otro universo. Aquí tienes una cheat sheet de colores. Esta web, o esta otra web, también están bien para orientarnos sobre la selección de (códigos) de colores. Cuando hagamos gráficos con ggplot2 comentaremos el tema de las paletas de colores. Ahora, vamos a replicar nuestro histograma pero seleccionamos un color mediante su código Hex.

hist(wage,
     breaks = 20,   
     main = "Distribución del Salario (dólares por hora)", 
     freq = FALSE,
     xlab = "Salario",                                          
     ylab = "Frecuencia relativa (en tanto por uno)", 
     xlim = c(0,50),
     ylim = c(0,0.15),
     col = "#ff9900",
     border = "#0040ff"
     )

curve(dnorm(x, mean=mean(wage), sd=sd(wage)), add=TRUE, col="#00ff00", lwd=3)

Por último, tal vez estemos interesados en indicar/señalar la posición de la media (o cualquier otra medida) en el histograma. Para hacer esto utilizamos la función abline().

hist(wage,
     breaks = 20,   
     main = "Distribución del Salario (dólares por hora)", 
     freq = FALSE,
     xlab = "Salario",                                          
     ylab = "Frecuencia relativa (en tanto por uno)", 
     xlim = c(0,50),
     ylim = c(0,0.15),
     col = "#ff9900",
     border = "#0040ff"
     )

curve(dnorm(x, mean=mean(wage), sd=sd(wage)), add=TRUE, col="#00ff00", lwd=3)

abline(v=mean(wage), lwd=2, lty=3, col="darkblue")    # añadimos posición de la media. Recordemos que e argumento "lwd"" hace referencia al grosor de la línea y "lty"" al tipo de línea.

Es momento de practicar lo aprendido. Ahí van dos tareas…

  • Tarea 1. Dibuja un histograma para ver la distribución de la experiencia (experience).
  • Tarea 2. Crea una nueva variable, log(wage), que sea el logaritmo del salario (wage). Dibuja el histograma de log(wage) y compararlo con el histograma de la variable original wage. ¿Qué conclusión puede extraerse?

Boxplot (diagrama de Caja y Bigotes)

En los gráficos Boxplot (o Box and Whiskers, más conocidos como Caja y Bigotes) se representan los cinco números (mínimo, cuartil 1, mediana, cuartil 3 y máximo), lo que nos puede ayudar a hacernos una idea de la asimetría de la distribución. Los gráficos de Caja y Bigotes también permiten detectar valores atípicos y outliers.

La función para representar los diagramas de Caja y Bigotes es boxplot(). Como siempre es recomendable echar un vistazo a los argumentos de la función.

?boxplot # recordar que también podemos escribir en la consola el nombre de la función y pulsar la tecla F1.

Vamos a hacer el boxplot de la variable wage.

boxplot(wage)

¿Qué podemos hacer para mejorar este gráfico?

Podemos incluir el título principal del gráfico, el nombre de la variable que estamos representando, colorear la caja y los bordes…

boxplot(wage,
        main = "Salario (dólares por hora)",
        ylab = "Salario",
        col = "pink",
        border = "purple"
        )

¿Cómo son los salarios de hombres y mujeres? Vamos a ver su distribución en un boxplot (básico).

boxplot(wage ~ gender)

Incluimos el título del gráfico e información sobre las variables que estamos representando.

boxplot(wage ~ gender,
        main = "Salario (dólares hora) según sexo",
        ylab = "Salario",
        names = c("Hombres","Mujeres")   # cambiamos la etiqueta de la variable cualitativa
        )

Se prefiere algunas veces presentar el boxplot en horizontal. También resulta muy ilustrativo incluir la media de salario según género. Para hacer esto último utilizamos la función points().

datos_mujeres <- subset(CPS1985, gender=="female")  # seleccionamos los datos de las mujeres
datos_hombres <- subset(CPS1985, gender=="male")    # seleccionamos los datos de los hombres

boxplot(wage ~ gender,
        main = "Salario (dólares hora) según género",
        ylab = "Salario",
        names = c("Hombres","Mujeres"),
        horizontal = T                 # boxplot en posición horizontal
        )

points(mean(datos_hombres$wage), 1, pch=25, bg="red")  # incluimos salario medio de hombres
points(mean(datos_mujeres$wage), 2, pch=22, bg="blue") # incluimos salario medio de mujeres

Para colorear el diagrama de Caja y Bigotes vamos a utilizar las paletas de colores (bueno, las paletas se utilizan para cualquier gráfico). Aquí puedes encontrar una Cheat sheet sobre este tema. Paletas de colores hay muchas, pero de las más utilizadas son:

  • rainbow
  • colorspace
  • RColorBrewer (ver más aquí)

Para gráficos sencillos también se utilizan las paletas topo.colors, cm.colors, heat.colors o terrain.colors. Nosotros mismos podemos definir nuestra propia paleta (hacer clic aquí para ver cómo hacerlo).

Veamos el efecto de algunas de las paletas a las que se ha hecho referencia.

  • Con rainbow
boxplot(wage ~ gender,
        main = "Salario (dólares hora) según género",
        ylab = "Salario",
        names = c("Hombres","Mujeres"),
        horizontal = T,
        col = rainbow(2)     # el número hace referencia al número de colores a utilizar. Puedes usar el argumento alpha también.
)

  • Con heat.colors
boxplot(wage ~ gender,
        main = "Salario (dólares hora) según género",
        ylab = "Salario",
        names = c("Hombres","Mujeres"),
        horizontal = T,
        col = heat.colors(2)
        )

  • Con colorspace. Para utilizar la paleta colorspace, primero hemos de cargar la librería y después seleccionamos la paleta que queremos. Finalmente, cargamos nuestra selección.
library(colorspace)
#pal <- choose_palette(diverge_hcl)  # para seleccionar la paleta que queremos

boxplot(wage ~ gender,
        main = "Salario (dólares hora) según género",
        ylab = "Salario",
        names = c("Hombres","Mujeres"), 
        horizontal = T,
        #col = pal(2)               # seleccionamos 2 colores de la paleta elegida
        )

Tal vez no hayamos percibido el efecto de las paletas porque hemos representado el salario (wage) en función de una variable categórica que solo tenía dos categorías (gender).

  • Tarea. Utilizando un boxplot, representar el salario (wage) en función de la ocupación (occupation). Incorpora al gráfico toda la información que se considere oportuna y utiliza distintas paletas de colores para ver los efectos.
boxplot(wage ~ occupation,
        main = "Salario (dólares hora) según ocupación",
        ylab = "Salario",
        xlab = "Ocupación",
        col = rainbow(6, alpha=0.2),
        border = rainbow(6, v=0.6)
        )

Con lo que hemos visto hasta ahora de gráficos, podemos darnos cuenta que en R tenemos realmente control sobre todos los elementos que componen el gráfico. Para un ejemplo, observemos los detalles del siguiente boxplot (basado en este post).

a <- rainbow(6)
b <- rainbow(6, alpha=0.2)
c <- rainbow(6, v=0.5)

boxplot(wage ~ occupation,
        col = b,          # color de relleno de la caja
        boxcol = c,       # color del borde de la caja
        medcol = c,       # color de la mediana (línea dentro de la caja)
        whiskcol = a,     # color de los bigotes
        staplecol = c,    # color de las líneas finales de los bigotes
        outcol = c,       # color de los puntos (atípicos y outliers)
        outbg = c,        # relleno de los puntos
        pch = 20,         # forma de los puntos
        cex = 1,          # tamaño de los puntos
        horizontal = T,   # cambiamos la posición de los diagramas a horizontal
        main = "Salario (dólares hora) según ocupación",
        ylab = "Ocupación",
        xlab = "Salario"
        )

Como vemos, al cambiar la orientación del gráfico se originan ciertos problemas de visualización. Debemos modificar los márgenes. Esta Cheat sheet es una buena ayuda para modificar los parámetros.

opar <- par()             # guardamos los parámetros por defecto
par(mar=c(5,6,4,2))      # modificamos los márgenes (inferios, izquierdo, superior, derecho) 

a <- rainbow(6)
b <- rainbow(6, alpha=0.2)
c <- rainbow(6, v=0.5)

boxplot(wage ~ occupation,
        col = b,         
        boxcol = c,      
        medcol = c,     
        whiskcol = a,   
        staplecol = c,    
        outcol = c,      
        outbg = c,      
        pch = 20,       
        cex = 1,          
        horizontal = T,   
        main ="Salario (dólares hora) según ocupación",
        xlab = "Salario",
        ylim = c(0,50),             # ampliamos el rango del eje
        las = 1,                    # cambiamos la orientación de las etiquetas
        frame = F                   # eliminamos el marco del gráfico
        )

par(opar)                  # volvemos a los parámetros originales
## Warning in par(opar): el parámetro del gráfico "cin" no puede ser especificado
## Warning in par(opar): el parámetro del gráfico "cra" no puede ser especificado
## Warning in par(opar): el parámetro del gráfico "csi" no puede ser especificado
## Warning in par(opar): el parámetro del gráfico "cxy" no puede ser especificado
## Warning in par(opar): el parámetro del gráfico "din" no puede ser especificado
## Warning in par(opar): el parámetro del gráfico "page" no puede ser especificado

Otra opción sería hacer referencia a las categorías de ocupación en una leyenda anexa al gráfico. Por ejemplo:

a <- rainbow(6)
b <- rainbow(6, alpha=0.2)
c <- rainbow(6, v=0.5)


boxplot(wage ~ occupation,
        col = b,       
        boxcol = c,     
        medcol = c,   
        whiskcol = a,  
        staplecol = c,   
        outcol = c,    
        outbg = c,     
        pch = 20,        
        cex = 1,         
        horizontal = T,  
        main = "Salario (dólares hora) según ocupación",
        xlab = "Salario",
        yaxt = "n"              # elminamos el eje y
        )

legend("bottomright", title="Salario (dólares hora)", levels(occupation), fill=b)

Diagrama de dispersión.

Los diagramas de dispersión permiten efectuar un diagnóstico visual de la posible relación (funcional) entre dos variables de naturaleza cuantitativa. La función que permite realizar este tipo de gráfico es plot(). Si solicitamos la ayuda de R sobre esta función (?plot), veremos que la función plot tiene un argumento llamado type que sirve para seleccionar el tipo de gráfico a dibujar. Las opciones de type son:

  • “p” para hacer un gráfico de puntos (es el tipo de gráfico por defecto).
  • “l” para hacer un gráfico de líneas.
  • “b” para hacer un gráfico de puntos y líneas (pero las líneas no entran en los puntos).
  • “c” para hacer un gráfico de líneas (parten de los puntos, sin entrar, pero no se representan).
  • “o” para hacer un gráfico de puntos y líneas (ahora las líneas entran en los puntos).
  • “h” para hacer un histograma o un diagrama de barras.
  • “s” para hacer un diagrama de escalera.

Por defecto la opción plot es type=p. Por tanto, si queremos hacer un diagrama de dispersión para representar la nube de puntos no será necesario indicar el tipo de gráfico.

Como la variable Salario presenta una importante dispersión y asimetría (ver histograma), vamos a representar el logaritmo del salario (log(wage)) en función de la experiencia (experience).

plot (experience, log(wage))

También lo podíamos haber escrito así:

plot (log(wage) ~ experience)

Como siempre, lo primero para mejorar la presentación de nuestro gráfico de dispersión será incluir el título del gráfico y de los ejes (también podemos incluir esta información utilizando la función title()

plot (log(wage) ~ experience,  
      main = "Salario (en logaritmos) en función de la experiencia",
      xlab = "Experiencia (en años)",
      ylab = "Salario (en logaritmos)"
      )

¿Queremos ver el salario en función de la experiencia y del género?

plot (log(wage) ~ experience,
      col = rainbow(2)[c(gender)],     # asigna color a los puntos en función del género
      main = "Salario (en logaritmos) en función de la experiencia",
      xlab = "Experiencia (en años)",
      ylab = "Salario (en logaritmos)"
      )

legend("topright", pch=16, col=rainbow(2), legend=c("Hombres","Mujeres")) # añadimos una leyenda al gráfico

Con la función abline() podemos añadir la recta de regresión en el diagrama de dispersión. Por ahora únicamente vamos a limitarnos a ver el efecto de la recta de regresión sobre el diagrama de dispersión. En otro curso estudiaremos, con cierta profundidad, los modelos de regresión con R.

# En primer lugar, obtenemos las regresiones
regresion_hombres <- lm(log(wage) ~ experience, data=CPS1985, subset=gender=="male")
regresion_mujeres <- lm(log(wage) ~ experience, data=CPS1985, subset=gender=="female")


plot (log(wage) ~ experience,
      col = rainbow(2)[c(gender)],     # asigna color a los puntos en función del género
      main = "Salario (en logaritmos) en función de la experiencia",
      xlab = "Experiencia (en años)",
      ylab = "Salario (en logaritmos)"
      )

legend("topright", pch=16, col=rainbow(2), legend=c("Hombres","Mujeres")) 

abline(regresion_hombres, col="red")
abline(regresion_mujeres, col="blue")

Un diagrama de dispersión alternativo al anterior.

sexo <- as.numeric(gender)

plot (log(wage) ~ experience,
      pch = sexo,
      col = sexo,
      main = "Salario (en logaritmos) en función de la experiencia",
      xlab = "Experiencia (en años)",
      ylab = "Salario (en logaritmos)"
      )

with(CPS1985[gender=="male",], abline(lm(log(wage)~experience), col="red"))
with(CPS1985[gender=="female",], abline(lm(log(wage)~experience), col="black"))

legend("topright", legend=c("Hombres","Mujeres"), pch=1:2, col=1:2, bty="y")

Para concluir, vamos a localizar el centro de gravedad (coordenadas correspondientes a las medias de las variables) en el gráfico de dispersión. Para ello usaremos la función points(). Como hay muchos puntos en el diagrama de dispersión, vamos a quitar los colores para poder ver donde cae el centro de gravedad.

sexo <- as.numeric(gender)

plot (log(wage) ~ experience,
      pch = sexo,
      main = "Salario (en logaritmos) en función de la experiencia",
      xlab = "Experiencia (en años)",
      ylab = "Salario (en logaritmos)"
      )

with(CPS1985[gender=="male",], abline(lm(log(wage)~experience), col="black"))
with(CPS1985[gender=="female",], abline(lm(log(wage)~experience), col="black"))

legend("topright", legend=c("Hombres","Mujeres"), pch=1:2, bty="y")

points(mean(experience), mean(log(wage)), pch=16, col="red")

y utilizando la función abline() podemos dibujar las rectas que pasan representar las líneas (quitamos las rectas de regresión para poder ver con mayor claridad el efecto).

sexo <- as.numeric(gender)

plot (log(wage) ~ experience,
      pch = sexo,
      main = "Salario (en logaritmos) en función de la experiencia",
      xlab = "Experiencia (en años)",
      ylab = "Salario (en logaritmos)"
      )
legend("topright", legend=c("Hombres","Mujeres"), pch=1:2, bty="y")

points(mean(experience), mean(log(wage)), pch=16, col="red")
abline(v=mean(experience), h=mean(log(wage)))

  • Tarea. Realizar un diagrama de dispersión para analizar la posible relación entre el salario (en logaritmos) y la edad (age) distinguiendo según la raza (ethnicity).

Diagrama de barras.

Para realizar un diagrama de barras primero tenemos que obtener la tabla de las frecuencias y después la representamos utilizando la función barplot().

Comenzamos realizando un diagrama de barras para ver la distribución de la variable Ocupación (Occupation).

frecuencias <- table(occupation)  # con variable categórica
frecuencias
## occupation
##     worker  technical   services     office      sales management 
##        156        105         83         97         38         55
## occupation
##     worker  technical   services     office      sales management 
##        156        105         83         97         38         55

barplot(frecuencias,
        col = heat.colors(6)
        )

Vamos a hacer un diagrama de barras con una variable discreta, por ejemplo: educación (education).

educacion <- table(education)
p <- barplot(educacion,
        col = 1:dim(educacion),       # para establecer el número de diferentes colores                                       (=diferentes valores)
        space = 0,                    # no espacio entre las barras
        horiz = F,                    # orientación de las barras
        density = 50 ,                # trama de las barras (se puede modificar el ángulo con                                     el argumento angle)
        ylim = c(0,250)
        )

title("Distribución de la edad", xlab= "Edad (en años)")
text(p[,1],educacion,labels=educacion, pos=3,cex=0.75)

Para ver cómo se distribuye una variable categórica según, generalmente, las categorías de una segunda variable suele utilizarse un diagrama de barras apiladas.

g <- table(ethnicity, gender) 

barplot(g,
        beside = F,                   # para apilar las barras
        col = rainbow(3),
        ylim = c(0,350)
        )
# Add text at top of bars
legend("topright", title="Raza", legend=levels(ethnicity), fill=rainbow(3), cex=.75, border=F, horiz=T, text.col="purple")

Observemos la diferencia del anterior gráfico respecto de este otro.

e <- table(gender, ethnicity) 

barplot(e,
        beside = F,  
        col = cm.colors(2),
        ylim = c(0,500),
        border = "blue"
        
)

p <- table(ethnicity, gender) 
barplot(p,
        beside=T,  # si es FALSE apila
        col=rainbow(3),
        legend=levels(ethnicity),
        names.arg= levels(gender),
        ylim=c(0,250)
        
)

Para dibujar diagramas de barras también se puede utilizar la función plot(). Aquí hay algún ejemplo:

plot(frecuencias, type=“h”)

plot(density(log(wage)))

plot (gender ~ occupation)

Otros gráficos básicos.

Gráficos de sectores

datos <- table(ethnicity)
pie(datos, 
    labels=c("Caucásicos", "Hispanos", "Otros"), 
    col=heat.colors(3),
    main= "Gráfico de sectores")

mosaicplot(ethnicity ~ occupation,
           col=2:5,
           main="Gráfico de mosaico",
           xlab="Raza",
           ylab="Ocupación",
           cex.axis=.5,
           las=1)

#install.packages("vcd")
library(vcd)
## Loading required package: grid
datos <- ftable(occupation, ethnicity, gender)
mosaic(~ occupation + ethnicity + gender , dat=datos, las=1)

3. Guardar y exportar gráficos

Si trabajamos con la interfaz que proporciona RStudio y queremos guardar o exportar un gráfico normalmente todo se hace con clicks.

4. ggplot2.

Una vez nos hemos familiarizado con la creación de gráficos (básicos) utilizando R base, en este apartado vamos a reproducir los gráficos que hemos ido trabajando pero haciendo uso de ggplot2. Creo que no nos equivocamos si decimos que, hoy en día, las representaciones gráficas en R pasan por ggplot2. Esta es la Cheat Sheet de RStudio con la ayuda para la visualización de datos con ggplot2.

Recomendamos revisar el manual “ggplot2. Elegant graphics for data analysis” de Wickham. Hay también una lista de ggplot (http://ggplot2.org/) a la que te puedes subscribir.

Un gráfico realizado con ggplot2 presenta, al menos, tres elementos:

Por tanto, para construir un gráfico con ggplot2 comenzamos con la siguiente estructura de código:

ggplot(datos, aes()) + geom_tipo()

A partir de esta estructura básica puede mejorarse la presentación de los gráficos introduciendo, por ejemplo, características estéticas en los objetos geométricos, rotulando el gráfico, etc.

Otros elementos que conviene tener presente en un gráfico de ggplot2 son:

Vamos a realizar algunos gráficos con ggplot. Para ello, cargamos la librería ggplot2. Si no está instalado el paquete lo instalamos.

#install.packages("ggplot2")
library(ggplot2)

En los ejemplos que siguen tratamos de ir introduciendo poco a poco distintos elementos y argumentos para mejorar la apariencia de los gráficos.

Histogramas

Vamos a comenzar haciendo un histograma muy sencillo del Salario (wage). Para ello, recordemos que la instrucción comienza con la función ggplot(), en la que incluimos los datos y la estética con la que queremos que se presenten en el gráfico. Seguidamente le añadimos (+) la geometría (tipo histograma) con la función geom_histogram().

Muy importante: con ggplot2 añadimos capas (layers) con el símbolo +.

El histograma del Salario será:

ggplot(CPS1985, aes(x=wage)) + 
  geom_histogram()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Dos cosas a considerar del histograma anterior:

  1. Por defecto, el número de intervalos es de 30. Es posible establecer el número de intervalos (bins), la amplitud del intervalo (binwidth) o fijar los puntos de corte de los intervalos (breaks).
  2. El eje Y corresponde al número de observaciones (frecuencias absolutas). Si estamos interesados en representar un histogramas de forma que el área del mismo sume 1, entonces tenemos que cambiar la estética de la siguiente forma:
ggplot(CPS1985, aes(x=wage)) + 
  geom_histogram(aes(y=..density..))
## 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.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

A partir de esta estructura básica, podemos ir añadiendo elementos para mejorar la presentación. Observa la diferencia entre los siguientes dos histogramas.

# Histograma con 20 intervalos
ggplot(CPS1985, aes(x=wage)) + 
  geom_histogram(bins=20, color="white", fill="blue")

# Histograma con amplitud de intervalo igual a 5. Línea discontinua para el contorno del intervalo
ggplot(CPS1985, aes(x=wage)) + 
  geom_histogram(binwidth=5, color="white", fill="blue", linetype=2)

Ahora vamos a insertar un título al gráfico y también rotularemos los ejes. Para modificar las etiquetas de los ejes se utilizan las funciones xlab() y ylab(). Si, por ejemplo, quisiéramos omitir la etiqueta del eje Y: ylab(NULL).

También podemos cambiar los límites de los ejes, para ello se emplean las funciones xlim() y ylim().

ggplot(CPS1985, aes(x=wage)) + 
  geom_histogram(bins=20, color="white", fill="blue") +
  ggtitle("Distribución del salario (dólares por hora)") +
  xlab("Salario") +
  ylab("Número de empleados")

# Una alternativa al anterior sería:
ggplot(CPS1985, aes(x=wage)) + 
  geom_histogram(bins=20, color="white", fill="blue") +
  labs(title = "Distribución del salario (dólares por hora)",
       x = "Salario",
       y = "Número de empleados") +
  ylim(c(0,150))

Para tratar de observar las diferencias en la distribución del salario según distintos grupo, por ejemplo, el género podemos:

  • Visualizar cada subconjunto de datos (salario para hombres y salario para mujeres) en distintos paneles. Para ello, utilizamos el elemento facet.
ggplot(CPS1985, aes(x=wage)) + 
  geom_histogram(bins=20, color="white", fill="blue") +
  facet_grid(gender~.)

ggplot(CPS1985, aes(x=wage)) + 
  geom_histogram(bins=20, color="white", fill="blue") +
  facet_wrap(~gender)

Hacemos el histograma pero usamos gender para colorear las partes que de cada intervalo corresponden a hombres y a mujeres. Fijémonos en los siguientes tres histogramas.

 ggplot(CPS1985, aes(x=wage)) +
  geom_histogram(bins=20, aes(color=gender) ) +
  ylim(c(0,150))

 ggplot(CPS1985, aes(x=wage, fill=gender)) +
  geom_histogram(bins=20) +
  ylim(c(0,150))

 ggplot(CPS1985, aes(x=wage)) +
  geom_histogram(bins=20, aes(fill=gender), position="fill", alpha=0.4) +
  labs(x= "Salario", y="Empleados", fill="Género") +  # títulos de ejes y leyenda
  scale_fill_discrete(labels=c("Hombre","Mujer"))     # títulos claves leyenda
## Warning: Removed 14 rows containing missing values (`geom_bar()`).

  • Representamos los polígonos de frecuencias de los distintos grupos.
 ggplot(CPS1985, aes(x=wage)) +
  geom_freqpoly(bins=20, aes(color=gender)) +
  labs(color="Género")

y va un poco mejor con la densidad de frecuencias:

 ggplot(CPS1985, aes(x=wage)) +
  geom_freqpoly(bins=20, aes(y=..density.., color=gender)) +
  labs(color="Género")

A continuación, vamos a añadir dos líneas para situar la media y la mediana.

ggplot(CPS1985, aes(x=wage)) + 
  geom_histogram(aes(fill=..count..), bins=20, color="white") +
  geom_vline(aes(xintercept=mean(wage)), color="red") +
  geom_vline(aes(xintercept=median(wage)), color= "darkgreen") +
  labs(title = "Distribución del salario (dólares por hora)",
       x = "Salario",
       y = "Número de empleados") +
  scale_fill_continuous(name="Empleados") +


  theme_classic() 

Añadimos la curva normal al histograma

ggplot(CPS1985, aes(x=wage)) + 
  geom_histogram(aes(y=..density..), bins=20, color="white", fill="grey") + 
  stat_function(fun = dnorm, colour = "red",
                arg = list(mean = mean(wage, na.rm = TRUE),
                             sd = sd(wage, na.rm = TRUE))) +
  geom_density(color="blue")
## Warning in stat_function(fun = dnorm, colour = "red", arg = list(mean =
## mean(wage, : Ignoring unknown parameters: `arg`

Con el argumento expand_limits podemos evitar que la curva de densidad aparezca unida. Veámoslo con el siguiente ejemplo:

ggplot(CPS1985, aes(x=wage)) + 
  geom_histogram(aes(y=..density..), bins=20, color="white", fill="grey") + 
  stat_function(fun = dnorm, colour = "red",
                arg = list(mean = mean(wage, na.rm = TRUE),
                                 sd = sd(wage, na.rm = TRUE))) +
  geom_line(stat="density", color="blue") +
  expand_limits(y=0)
## Warning in stat_function(fun = dnorm, colour = "red", arg = list(mean =
## mean(wage, : Ignoring unknown parameters: `arg`

Podemos consultar las siguientes dos páginas web para aprender más sobre cómo crear histogramas con ggplot2:

Ahora ha llegado el momento de que practiquemos lo visto en este apartado del tutorial.

  • Tarea: Representa la distribución del salario (en logaritmos: log(wage)) mediante un histograma. Compara la distribución de log(wage) según la raza (ethnicity).

Diagramas de caja

Para realizar un diagrama de caja utilizamos la geometría: geom_boxplot().

ggplot(CPS1985, aes(x=gender, y=wage)) +
  geom_boxplot()

Podemos colorear las cajas del gráfico incluyendo en las características estéticas la variable que utilizaremos para el relleno. Automáticamente se crea una leyenda para facilitar la lectura del gráfico que podemos cambiar de posición o eliminar si se considera que no aporta información relevante.

# Diagrama de caja con color de relleno
ggplot(CPS1985, aes(x=gender, y=wage, fill=gender)) +
  geom_boxplot() +
  labs(x="Sexo", y="Salario", fill="Género") +   # titulo ejes y leyenda
  scale_x_discrete(labels=c("Hombre","Mujer")) +   # etiquetas del eje x
  scale_fill_discrete(labels=c("Hombre","Mujer"))  # etiquetas claves leyenda

# Diagrama de caja con cambio de posición de la leyenda
ggplot(CPS1985, aes(x=gender, y=wage, fill=gender)) +
  geom_boxplot() +
  labs(x="Sexo", y="Salario", fill="Género") +  
  scale_x_discrete(labels=c("Hombre","Mujer")) +
  scale_fill_discrete(labels=c("Hombre","Mujer")) + 
  theme(legend.position="top")   # cambio posición de leyenda

# Diagrama de caja sin leyenda por considerar redundante la información
ggplot(CPS1985, aes(x=gender, y=wage, fill=gender)) +
  geom_boxplot(outlier.colour = "blue") +             # color de los outliers
  labs(x="Sexo", y="Salario") +  
  scale_x_discrete(labels=c("Hombre","Mujer")) +
  guides(fill=FALSE)                                  # eliminamos la leyenda
## Warning: The `<scale>` argument of `guides()` cannot be `FALSE`. Use "none" instead as
## of ggplot2 3.3.4.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

Para cambiar la orientación de las cajas y que en lugar de representarse verticalmente se representen horizontalmente se utiliza la función coord_flip(). Esta forma de presentar los diagramas de caja es muy frecuente porque facilita la interpretación de los mismos al situar la variable cuantitativa en el eje de abscisas.

  ggplot(CPS1985, aes(x=gender, y=wage, fill=gender)) +
  geom_boxplot(outlier.colour = "blue") +            
  labs(x="Sexo", y="Salario") +  
  scale_x_discrete(labels=c("Hombre","Mujer")) +
  guides(fill=FALSE) +
  coord_flip()                       # cambio dirección de las cajas

Puede resultar interesante localizar la media de cada grupo en los diagramas de caja. Para ello, hacemos uso del elemento stat (transformación estadística). Se puede añadir stat, básicamente, de dos formas:

    1. añadir directamente una función stat_() y de esa forma anular su valor por defecto en la geometría.
    1. añadir una función geom_() e introducir el elemento stat para anular el valor por defecto.

Veamos las dos formas comentadas de añadir .

# Añadimos la media utilizando la función stat_()
ggplot(CPS1985, aes(x=gender, y=wage, fill=gender)) +
  geom_boxplot() +
  labs(x="Sexo", y="Salario") +  
  scale_x_discrete(labels=c("Hombre","Mujer")) +
  guides(fill=FALSE) +
  coord_flip() +                  
  stat_summary(fun.y=mean, geom="point", shape=5, size=4)
## Warning: The `fun.y` argument of `stat_summary()` is deprecated as of ggplot2 3.3.0.
## ℹ Please use the `fun` argument instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

# Añadimos la media utilizando la función geom_() y modificando el elemento stat
ggplot(CPS1985, aes(x=gender, y=wage, fill=gender) ) +
  geom_boxplot(alpha=0.3, outlier.colour = "blue") +
  labs(x="Género", y="Salario") +  
  scale_x_discrete(labels=c("Hombre","Mujer")) +
  guides(fill=FALSE) +
  coord_flip() +              
  geom_point(stat= "summary", fun.y=mean, shape=16, size=2, color="red")
## Warning in geom_point(stat = "summary", fun.y = mean, shape = 16, size = 2, :
## Ignoring unknown parameters: `fun.y`
## No summary function supplied, defaulting to `mean_se()`

Por último, si queremos hacernos una idea de cómo se distribuyen nuestras observaciones/individuos respecto del diagrama de caja podemos hacer uso de la función position_jitter(). Cuando hay muchos datos las observaciones se superponen. La función position_jitter() lo que hace es añadir un pequeño “ruido” en cada posición. También podemos utilizar la geometría geom_jitter(). A continuación se muestran los diagramas de caja con estas dos opciones.

ggplot(CPS1985, aes(x=gender, y=wage, fill=gender) ) +
  geom_boxplot(alpha=0.3, outlier.colour = "blue") +
  labs(x="Sexo", y="Salario") +
  scale_x_discrete(labels=c("Hombre","Mujer")) +
  guides(fill=FALSE) +
  coord_flip() +              
  geom_point(stat= "summary", fun.y=mean, shape=16, size=4, color="red") +
  geom_point(position = position_jitter(width = 0.1), alpha = 0.2)
## Warning in geom_point(stat = "summary", fun.y = mean, shape = 16, size = 4, :
## Ignoring unknown parameters: `fun.y`
## No summary function supplied, defaulting to `mean_se()`

ggplot(CPS1985, aes(x=gender, y=wage, fill=gender) ) +
  geom_boxplot(alpha=0.3, outlier.colour = "blue") +
  labs(x="Salario", y="Salario") +
  scale_x_discrete(labels=c("Hombre","Mujer")) +
  guides(fill=FALSE) +
  coord_flip() +              
  geom_point(stat= "summary", fun.y=mean, shape=16, size=4, color="red") +
  geom_jitter(width = 0.1, alpha = 0.2)
## Warning in geom_point(stat = "summary", fun.y = mean, shape = 16, size = 4, :
## Ignoring unknown parameters: `fun.y`
## No summary function supplied, defaulting to `mean_se()`

Para practicar lo aprendido proponemos la siguiente tarea:

  • Tarea: Representa el diagrama de caja del salario (wage) en función de la ocupación (occupation). Incorpora al gráfico toda la información que se considere oportuna.

Diagramas de dispersión

Ya hemos visto a lo largo de este tutorial que el salario presenta una gran dispersión y su distribución es asimétrica. Sin embargo, si transformamos el salario y trabajamos con el logaritmo del salario, tanto la dispersión como la asimetría se reducen. Cuando trabajamos con variables monetarias esta situación suele ser frecuente y, por tanto, normalmente se trabaja con logaritmos.

¿Cómo es la relación entre el salario (en logaritmos) y la experiencia?

Hacemos el diagrama de dispersión para ver la posible relación entre ambas variables.

ggplot(CPS1985, aes(experience, log(wage))) +
  geom_point() +
  labs(title="Diagrama de dispersión",
       subtitle= "ScatterPlot",
       caption="Fuente: CPS1985 (paquete AER)",
       x="Experiencia (en años)",
       y="Salario (en logaritmo)")

Si queremos que los puntos del diagrama de dispersión tengan color tenemos varias alternativas. Observar las diferencias entre los siguientes tres gráficos.

# Opción 1
ggplot(CPS1985, aes(experience, log(wage), color="red")) +
  geom_point()

# Opción 2
ggplot(CPS1985, aes(experience, log(wage))) +
  geom_point(aes(color="red"))

# Opción 3
ggplot(CPS1985, aes(experience, log(wage))) +
  geom_point(color="red")

Las dos primeras opciones -en las que color se ha introducido como una característica estética (con aes())- tienen un efecto similar (no necesariamente igual): se crea una variable color que toma el valor red y automáticamente se muestra una leyenda. En la tercera opción el color se introduce como una constante.

Si tenemos muchos datos es muy probable que se produzca un importante solapamiento de las observaciones. Si “muchos datos” no son “muchísimos”, podemos utilizar jitter para introducir una pequeña perturbación en las observaciones y mejorar la visualización de los datos con el diagrama de dispersión.

ggplot(CPS1985, aes(experience,log(wage))) +
  geom_jitter(width=.2, alpha=0.5) +
  labs(title="Diagrama de dispersión",
       subtitle= "ScatterPlot",
       caption="Fuente: CPS1985 (paquete AER)",
       x="Experiencia (en años)",
       y="Salario (en logaritmo)")

Una alternativa al gráfico anterior es representar lo que se conoce como Hex plot. Este gráfico es equivalente a un histograma en el sentido que se representan puntos hexagonales con distinto color en función del número de observaciones que caen dentro de cada hexágono.

# install.packages("hexbin")    # Hay que instalar el paquete hexbin
library(hexbin)

ggplot(CPS1985, aes(experience,log(wage))) +
  geom_hex() +
  labs(title="Diagrama de dispersión",
       subtitle= "ScatterPlot",
       caption="Fuente: CPS1985 (paquete AER)",
       x="Experiencia (en años)",
       y="Salario (en logaritmo)") +
  scale_fill_continuous("Empleados") +
  theme_classic()

Cuando se utiliza la geometría geom_hex los puntos hexagonales se colorean, por defecto, según una escala gradual de tonos azules (azul oscuro equivale a poca frecuencia, azul claro equivale a alta frecuencia). Esto no es muy intuitivo para nosotros: ¿claro mucha frecuencia?, ¿oscuro poca frecuencia?. Al revés estamos más acostumbrados. Podemos cambiar la escala de colores utilizando la función scale_fill_gradient.

ggplot(CPS1985, aes(experience,log(wage))) +
  geom_hex() +
  labs(title="Diagrama de dispersión",
       subtitle= "ScatterPlot",
       caption="Fuente: CPS1985 (paquete AER)",
       x="Experiencia (en años)",
       y="Salario (en logaritmo)") +
  scale_fill_gradient("Empleados", low="orange", high="orange4") +  # nombres en colors()
  theme_classic()

Ahora, en el diagrama de dispersión vamos a colorear los puntos según el sexo Observa las diferencias entres los siguientes tres diagramas de dispersión. ¿Alguna diferencia entre los siguientes dos gráficos?

# Opción 1
ggplot(CPS1985, aes(experience,log(wage), color=gender)) +
  geom_point() +
  labs(title="Diagrama de dispersión",
       subtitle= "ScatterPlot",
       caption="Fuente: CPS1985 (paquete AER)",
       x="Experiencia (en años)",
       y="Salario (en logaritmo)") +
  scale_color_discrete(name="Género", labels=c("Hombre","Mujer"))

# Opción 2
ggplot(CPS1985, aes(experience,log(wage))) +
  geom_point(aes(color=gender)) +
    labs(title="Diagrama de dispersión",
       subtitle= "ScatterPlot",
       caption="Fuente: CPS1985 (paquete AER)",
       x="Experiencia (en años)",
       y="Salario (en logaritmo)") +
  scale_color_discrete("Sexo", labels=c("Hombre","Mujer"))

Como comentamos anteriormente, aparentemente no hay diferencias entre los dos gráficos, pero fijémonos qué sucede si añadimos la recta de regresión. Esto último lo vamos a hacer añadiendo la geometría geom_smooth() y especificando como método de estimación lm (linear model).

# Opción 1
ggplot(CPS1985, aes(experience,log(wage), color=gender)) +
  geom_point() +
  geom_smooth(method="lm", se=FALSE) +  
  labs(title="Diagrama de dispersión",
       subtitle= "ScatterPlot",
       caption="Fuente: CPS1985 (paquete AER)",
       x="Experiencia (en años)",
       y="Salario (en logaritmo)") +
  scale_color_discrete("Género", labels=c("Hombre","Mujer"))
## `geom_smooth()` using formula = 'y ~ x'

# Opción 2
ggplot(CPS1985, aes(experience,log(wage))) +
  geom_point(aes(color=gender)) +
  geom_smooth(method="lm") +
  labs(title="Diagrama de dispersión",
       subtitle= "ScatterPlot",
       caption="Fuente: CPS1985 (paquete AER)",
       x="Experiencia (en años)",
       y="Salario (en logaritmo)") +
  scale_color_discrete("Género", labels=c("Hombre","Mujer"))
## `geom_smooth()` using formula = 'y ~ x'

Para más detalles prácticos sobre los diagramas de dispersión puedes consultar, por ejemplo, ggplot2 scatter plots : Quick start guide - R software and data visualization o Scatterplots (ggplot2) en Cookbook for R.

Es el momento de realizar una nueva tarea:

Tarea: Realizar un diagrama de dispersión utilizando la base de datos CPS1988 del paquete AER. Incluye en el gráfico colores según una determinada variable categórica, rectas de regresión, cambiar la posición de la leyenda y cualquier otro detalle que consideres oportuno.

Diagramas de barras

El diagrama de barras, como ya sabemos, puede utilizarse para representar variables categóricas (atributos u ordinales) y variables cuantitativas discretas.

ggplot(CPS1985, aes(ethnicity)) +
  geom_bar()

ggplot(CPS1985, aes(education)) +
  geom_bar()

Como siempre, lo primero sería dar título al gráfico y a los ejes.

ggplot(CPS1985, aes(ethnicity)) +
  geom_bar() +
  labs(title="Diagrama de barras",
       x= "Raza",
       y="Empleados") +
  scale_x_discrete(labels=c("Caucásico", "Hispano", "Otros"))

ggplot(CPS1985, aes(education)) +
  geom_bar() +
    labs(title="Diagrama de barras",
         x= "Educación (en años)",
         y="Empleados")

Coloreamos cada barra con un color distinto:

ggplot(CPS1985, aes(ethnicity, fill=ethnicity)) +
  geom_bar() +
  labs(title="Diagrama de barras",
       x= "Raza",
       y="Empleados") +
  scale_x_discrete(labels=c("Caucásico", "Hispano", "Otros")) 

# eliminamos la leyenda porque en este caso no es ilustrativa
ggplot(CPS1985, aes(ethnicity, fill=ethnicity)) +
  geom_bar() +
  labs(title="Diagrama de barras",
       x= "Raza",
       y="Empleados") +
  scale_x_discrete(labels=c("Caucásico", "Hispano", "Otros")) +  
  guides(fill=FALSE)

Incorporamos información sobre el número de casos en las barras correspondientes a cada categoría y eliminamos el eje Y.

ggplot(CPS1985, aes(ethnicity, fill=ethnicity)) +
  geom_bar() +
  labs(title="Diagrama de barras",
       x= "Raza",
       y=NULL) +
  scale_x_discrete(labels=c("Caucásico", "Hispano", "Otros")) +  
  guides(fill=FALSE) +
  geom_text(stat='count',aes(label=..count..), vjust=-0.5, size=3) 

Ahora estamos interesados en ver cómo se distribuye el sexo según la raza.

ggplot(CPS1985, aes(ethnicity, fill=gender)) +
  geom_bar() +
  labs(title="Diagrama de barras",
       x= "Raza",
       y="Empleados") +
  scale_x_discrete(labels=c("Caucásico", "Hispano", "Otros")) +
  scale_fill_discrete("Sexo", labels=c("Hombre","Mujer"))

Si queremos otros colores los podemos introducir manualmente o a través de una paleta:

ggplot(CPS1985, aes(ethnicity, fill=gender)) +
  geom_bar() +
  labs(title="Diagrama de barras",
       x= "Raza",
       y="Empleados") +
  scale_x_discrete(labels=c("Caucásico", "Hispano", "Otros")) +
  scale_fill_manual(values=c("#FF0033", "#3300FF"),
                    "Sexo",
                    labels=c("Hombre","Mujer"))

# Ejemplo 1. Paleta de colores
ggplot(CPS1985, aes(ethnicity, fill=gender)) +
  geom_bar() +
  labs(title="Diagrama de barras",
       x= "Raza",
       y="Empleados") +
  scale_x_discrete(labels=c("Caucásico", "Hispano", "Otros")) +
  scale_fill_manual(values = heat.colors(2),
                    "Sexo",
                    labels=c("Hombre","Mujer"))

# Ejemplo 2. Paleta de colores
ggplot(CPS1985, aes(ethnicity, fill=gender)) +
  geom_bar() +
  labs(title="Diagrama de barras",
       x= "Raza",
       y="Empleados") +
  scale_x_discrete(labels=c("Caucásico", "Hispano", "Otros")) +
  scale_fill_brewer(palette = "Accent",
                    "Sexo",
                    labels=c("Hombre","Mujer"))

Como hicimos antes, incluimos el número de casos como parte de la información que proporciona el diagrama de barras.

ggplot(CPS1985, aes(ethnicity, fill=gender)) +
  geom_bar() +
  labs(title="Diagrama de barras",
       x= "Raza",
       y="Empleados") +
  scale_x_discrete(labels=c("Caucásico", "Hispano", "Otros")) +
  scale_fill_brewer(palette = "Accent",
                    "Sexo",
                    labels=c("Hombre","Mujer")) +
  geom_text(stat='count',aes(label=..count..),
            position = "stack",
            vjust=1,
            size=2,
            color="red")

El mismo diagrama de barras apilado pero ahora en porcentajes:

ggplot(CPS1985, aes(ethnicity,y = (..count..)/sum(..count..), fill=gender)) +
  geom_bar() +
  labs(title="Diagrama de barras",
       x= "Raza",
       y="Empleados") +
  scale_x_discrete(labels=c("Caucásico", "Hispano", "Otros")) +
  scale_fill_brewer(palette = "Accent",
                    "Sexo",
                    labels=c("Hombre","Mujer")) +
  geom_text(stat="count", 
            aes(label = paste(round((..count..)/sum(..count..)*100), "%")),
            position = "stack",
            vjust=1,
            size=3,
            color="red")

Y para ver la proporción de hombres y mujeres en cada categoría hacemos uso del parámetro position = fill dentro de la geometría.

ggplot(CPS1985, aes(ethnicity, fill=gender)) +
  geom_bar(position = "fill") +
  labs(title="Diagrama de barras",
       x= "Raza",
       y="Empleados") +
  scale_x_discrete(labels=c("Caucásico", "Hispano", "Otros")) +
  scale_fill_brewer(palette = "Accent",
                    "Sexo",
                    labels=c("Hombre","Mujer")) 

Como hemos podido comprobar hasta ahora, cuando hacemos un diagrama de barras en el que consideramos más de una variable categórica, las barras aparecen apiladas (la opción por defecto es position = “stack”). Podemos hacer que las barras se sitúen unas junto a las otras con position = “dodge”.

ggplot(CPS1985, aes(ethnicity, fill=gender)) +
  geom_bar(position="dodge") +            # también: position=position_dodge()
  labs(title="Diagrama de barras",
       x= "Raza",
       y="Empleados") +
  scale_x_discrete(labels=c("Caucásico", "Hispano", "Otros")) +
  scale_fill_brewer(palette = "Accent",
                    "Género",
                    labels=c("Hombre","Mujer"))

y, finalmente, podemos cambiar la orientación de las barras de vertical a horizontal.

ggplot(CPS1985, aes(ethnicity, fill=gender)) +
  geom_bar(position="dodge") +            # también: position=position_dodge()
  labs(title="Diagrama de barras",
       x= "Raza",
       y="Empleados") +
  scale_x_discrete(labels=c("Caucásico", "Hispano", "Otros")) +
  scale_fill_brewer(palette = "Accent",
                    "Género",
                    labels=c("Hombre","Mujer")) +
  coord_flip()

En R para muy principiantes encontrarás una serie de cuatro video-blogs sobre cómo elaborar un diagrama de barras en ggplot2.

6. Más referencias y sugerencias.

Libros: