El ggplot2 es un paquete de datos que nos permite realizar diversos tipos gráficos de alta calidad, manipulando con detalle la manera cómo queremos que se vea el gráfico.
Trabaja con objetos tipo data frame para extraer la información que se quiere graficar.
Un ejemplo es un gráfico de barras del porcentaje de personas que tiene o no computadora en su casa. Para ello primero debemos crear la tabla:
library(foreign)
genero12 <- read.spss("IOP_1212_01_D.sav", to.data.frame = TRUE,
use.value.labels = TRUE)
computadora <- prop.table(table(genero12$P81E))*100
computadora
##
## Sí No
## 45.38591 54.61409
Para generar el gráfico la tabla debe convertirse primero en un data frame:
computadora <- as.data.frame(computadora)
computadora
## Var1 Freq
## 1 Sí 45.38591
## 2 No 54.61409
Gráfico de barras en ggplot2:
library(ggplot2)
ggplot(computadora, aes(x=Var1, y=Freq)) + geom_bar(stat = "identity")
Un gráfico en ggplot se construye combinando una serie de elementos que se añaden en formas de capas y que en su conjunto producirán la forma final del gráfico:
La primera capa contiene los siguientes elementos:
ggplot(computadora, aes(x=Var1, y=Freq))
Si bien hay varias estéticas, las más utilizadas son: + y e y para las información que será puesta en los respectivos ejes horizontal y vertical + colour para el color + shape para la forma de los puntos + fill para el relleno de barras
Los geoms son instrucciones que nos indican cómo debemos represtar las estéticas en el gráfico, es decir las formas específicas que usaremos para representar los datos: barras, líneas, puntos, cajas, histogramas, densidades, etc. En los geoms también podemos añadir instrucciones específicas. Por ejemplo:
# Gráfico básico
ggplot(computadora, aes(x=Var1, y=Freq)) +
geom_bar(stat = "identity")
# Gráfico con colores diferentes para las categorías del eje x
ggplot(computadora, aes(x=Var1, y=Freq, fill=Var1)) +
geom_bar(stat = "identity")
# Añadimos una línea de contorno negra para las barras del gráfico
ggplot(computadora, aes(x=Var1, y=Freq, fill=Var1)) +
geom_bar(stat = "identity", color = "black")
# Quitamos la leyenda que resulta redundante
ggplot(computadora, aes(x=Var1, y=Freq, fill=Var1)) +
geom_bar(stat = "identity", color = "black") +
guides(fill = FALSE)
Las siguientes capas nos permiten personalizar diferentes aspectos del gráfico, tales como:
Por ejemplo si queremos completar el gráfico anterior:
ggplot(computadora, aes(x=Var1, y=Freq, fill=Var1)) +
geom_bar(stat = "identity", color = "black") +
guides(fill = FALSE) +
ylim(0, 80) + xlab("Tiene equipo") + ylab("% de entrevistados") +
ggtitle("Porcentaje de estrevistados que declaran tener computadora en el hogar")
El mismo gráfico con un tema en Blanco y Negro:
ggplot(computadora, aes(x=Var1, y=Freq, fill=Var1)) +
geom_bar(stat = "identity", color = "black") +
guides(fill = FALSE) +
ylim(0, 80) + xlab("Tiene equipo") + ylab("% de entrevistados") +
ggtitle("Porcentaje de estrevistados que declaran tener computadora en el hogar") +
theme_bw()
Para realizar gráficos de barras múltiples, debemos partir de una tabla de frecuencias cruzadas. Por ejemplo, el porcentaje de personas que tienen computadora según nivel socioeconómico del hogar:
comput.2 <- prop.table(table(genero12$P81E, genero12$NSEGrup),2)*100
comput.2
##
## A/B C D/E
## Sí 95.81749 65.05682 10.39861
## No 4.18251 34.94318 89.60139
comput.2 <- as.data.frame(comput.2)
comput.2
## Var1 Var2 Freq
## 1 Sí A/B 95.81749
## 2 No A/B 4.18251
## 3 Sí C 65.05682
## 4 No C 34.94318
## 5 Sí D/E 10.39861
## 6 No D/E 89.60139
## Barras apiladas
ggplot(comput.2, aes(x=Var2, y=Freq, fill = Var1)) +
geom_bar(stat = "identity")
## Barras paralelas, se añade la opción position = position_dodge()
ggplot(comput.2, aes(x=Var2, y=Freq, fill = Var1)) +
geom_bar(stat = "identity", position = position_dodge())
Versión final del gráfico:
ggplot(comput.2, aes(x=Var2, y=Freq, fill = Var1)) +
geom_bar(stat = "identity", color = "black") +
xlab("Niveles socioeconómicos") +
ylab("% de entrevistados") +
scale_fill_discrete(name = "Tiene equipo") +
ggtitle("Tenencia de computadora por nivel socioeconómico del entrevistado \nPorcentaje según niveles socioeconómicos") +
theme_bw()
Otra versión alternativa del gráfico en escala de grises y con subtítulo:
ggplot(comput.2, aes(x=Var2, y=Freq, fill = Var1)) +
geom_bar(stat = "identity", color = "black") +
xlab("Niveles socioeconómicos") +
ylab("% de entrevistados") +
scale_fill_brewer(name = "Sexo", palette = "Greys") +
labs(title = "Tenencia de computadora por nivel socioeconómico del entrevistado",
subtitle = "% Según niveles socioeconómicos") +
theme_bw()
Otra versión alternativa del gráfico con colores ad-hoc llenados en forma manual y con subtítulo:
Nota: Para ver más opciones sobre cómo trabajar con colores en gplot2 seguir el siguiente enlace
ggplot(comput.2, aes(x=Var2, y=Freq, fill = Var1)) +
geom_bar(stat = "identity", color = "black") +
xlab("Niveles socioeconómicos") +
ylab("% de entrevistados") +
scale_fill_manual(name = "Sexo", values = c("#FF6600", "#330066")) +
labs(title = "Tenencia de computadora por nivel socioeconómico del entrevistado",
subtitle = "% Según niveles socioeconómicos") +
theme_bw()
Histograma
El geom para histograma es: geom_histogram. Con la opción bindwidht = se puede especificar la amplitud de los intervalos de x que representa cada barra:
# Histograma de amplitud 2 (cada barra representa dos años)
ggplot(genero12, aes(x = EDAD)) + geom_histogram(binwidth = 2, color = "white") +
ggtitle("Histograma de Edades de los Entrevistados (intervalos de 2 años)") + xlab("Edades") +
ylab("Frecuencia") + theme_bw()
# Histograma de amplitud 4 (cada barra representa cuatro años)
ggplot(genero12, aes(x = EDAD)) + geom_histogram(binwidth = 4, color = "white") +
ggtitle("Histograma de Edades de los Entrevistados (intervalos de 4 años)") + xlab("Edades") +
ylab("Frecuencia") + theme_bw()
Gráfico de densidad:
# Densidad simple
ggplot(genero12, aes(x=P19A)) + geom_density() +
xlab("Horas") + ylab("Densidad") +
ggtitle("Horas dedicadas a labores domésticas") +
theme_bw()
# Densidad por grupos, diferenciado por colores
ggplot(genero12, aes(x=P19A, color = SEXO)) + geom_density() +
xlab("Horas") + ylab("Densidad") +
ggtitle("Horas dedicadas a labores domésticas, según sexo") +
theme_bw()
# Densidad por grupos, diferenciado por tipo de línea y con líneas más gruesas
ggplot(genero12, aes(x=P19A, linetype = SEXO)) + geom_density(size = 2) +
xlab("Horas") + ylab("Densidad") +
ggtitle("Horas dedicadas a labores domésticas, según sexo") +
theme_bw()
Hagamos el gráfico de cajas del índice de homofobia. Primero hay que calcular el índice:
# Índice de Homofobia
library(dplyr)
homofob <- genero12[, c(111:117)]
homofob <- homofob %>% mutate_if(is.factor, as.numeric)
homofob <- homofob %>% mutate_all(~dplyr::recode(., '5'= NaN))
homofob <- homofob %>% mutate_all(~((. -4)*(-1)))
genero12$i.homofob <- rowSums(homofob)/21*100
# Boxplot simple horizontal
ggplot(genero12, aes(i.homofob)) + geom_boxplot()
# Boxplot simple vertical
ggplot(genero12, aes(y=i.homofob)) + geom_boxplot()
Boxplot agrupado por ámbito de residencia:
ggplot(genero12, aes(x=Ambito, y=i.homofob)) + geom_boxplot() +
ylab("Índice de Homofobia") +
ggtitle("Índice de Homofobia según Ámbito de Residencia") +
theme_bw()
Boxplot agrupado por ámbito de residencia y grupo de edad
ggplot(genero12, aes(x=Ambito, y=i.homofob, fill = GEDAD)) + geom_boxplot() +
ylab("Índice de Homofobia") +
ggtitle("Índice de Homofobia según Ámbito de Residencia y Grupos de Edad") +
scale_fill_discrete(name = "Grupo de Edad") +
theme_bw()
En este caso usaremos como ejemplo la variable “horas dedicadas a labores domésticas”:
library(doBy)
tab2 <- summaryBy(P19A ~ SEXO + GEDAD, data = genero12,
FUN = function(x) {c(Media = mean(x, na.rm = T),
Md = median(x, na.rm = T),
Desv = sd(x, na.rm = T),
Rg = range(x, na.rm = T))})
tab2
## SEXO GEDAD P19A.Media P19A.Md P19A.Desv P19A.Rg1 P19A.Rg2
## 1 Masculino 18 a 29 13.51232 10 12.67896 0 70
## 2 Masculino 30 a 44 13.70588 10 14.26531 0 84
## 3 Masculino 45 a más 13.89340 10 13.65216 0 70
## 4 Femenino 18 a 29 28.49275 21 25.71650 0 168
## 5 Femenino 30 a 44 34.46701 28 25.04965 0 168
## 6 Femenino 45 a más 33.91905 28 21.82199 0 112
# Gráfico con barras que representan a la media de las horas
# En el título el código "\n" inserta un salto de línea, sirve para cortar títulos largos
ggplot(tab2, aes(x=GEDAD, y=P19A.Media, fill=SEXO)) +
geom_bar(stat = "identity", position = position_dodge(), color = "black") +
xlab("Grupos de Edad") + ylab("Horas") +
scale_fill_brewer(name = "Sexo", palette = "Greys") +
ggtitle("Promedio de horas semanales dedicadas a labores domésticas, \nsegún sexo y grupos de edad") +
theme_bw()
# Gráfico con puntos que representan a la media de las horas
ggplot(tab2, aes(x=GEDAD, y=P19A.Media, shape=SEXO)) +
geom_point(size = 3) + ylim(10, 40) +
xlab("Grupos de Edad") + ylab("Horas") +
ggtitle("Promedio de horas semanales dedicadas a labores domésticas, \nsegún sexo y grupos de edad") +
theme_bw()
Gráfico de puntos y líneas: Horas dedicadas a labores domésticas según número de hijos y sexo del entrevistado
# Primero agrupamos el número de hijos en categorías
library(car)
genero12$hijos.men <- factor(recode(genero12$P44B,
"NA=0; 1=1; 2=2; 3:hi=3"),
labels = c("Ninguno", "Uno", "Dos", "Tres o más"))
tab4 <- summaryBy(P19A ~ SEXO + hijos.men, data = genero12,
FUN = function(x) {c(Media = mean(x, na.rm = T),
Md = median(x, na.rm = T),
Desv = sd(x, na.rm = T),
Rg = range(x, na.rm = T),
quantile(x, probs = c(0.25, .75), na.rm=T))})
ggplot(tab4, aes(x=hijos.men, y=P19A.Media, group = SEXO, shape= SEXO, linetype = SEXO)) +
geom_point(size=3) + geom_line(stat = "identity") +
scale_shape_discrete(name = "Sexo") + scale_linetype_discrete(name = "Sexo") +
ylim(0, 50) + xlab("Número de hijos") + ylab("Horas") +
ggtitle("Promedio de horas semanales dedicadas a labores \ndomésticas, según número de hijos y sexo del entrevistado") + theme_bw()
El ggplot nos permite realizar el mismo gráfico para diferentes grupos de casos en la forma de facetas.
Por ejemplo, según grupo de edad por ámbito de residencia:
# Facetas verticales
ggplot(genero12, aes(x=GEDAD, y=i.homofob)) + geom_boxplot() +
ylab("Índice de Homofobia") +
xlab("Grupos de edad") +
ggtitle("Índice de Homofobia según Grupos de Edad, por ámbito de residencia") +
facet_grid(Ambito ~ .) +
theme_bw()
# Facetas horizontales
ggplot(genero12, aes(x=GEDAD, y=i.homofob)) + geom_boxplot() +
ylab("Índice de Homofobia") +
xlab("Grupos de edad") +
ggtitle("Índice de Homofobia según Grupos de Edad, por ámbito de residencia") +
facet_grid(.~ Ambito) +
theme_bw()
# Facetas en forma de reloj
ggplot(genero12, aes(x=GEDAD, y=i.homofob)) + geom_boxplot() +
ylab("Índice de Homofobia") +
xlab("Grupos de edad") +
ggtitle("Índice de Homofobia según Grupos de Edad, por dominio geográfico") +
facet_wrap(~ DOMINIO) +
theme_bw()
# Facetas que combinan dos variables de agrupación:
ggplot(genero12, aes(x=GEDAD, y=i.homofob)) + geom_boxplot() +
ylab("Índice de Homofobia") +
xlab("Grupos de edad") +
ggtitle("Índice de Homofobia según Grupos de Edad, por sexo y ámbito de residencia") +
facet_grid(SEXO ~ Ambito) +
theme_bw()
El ggplot2, combinado en ocasiones con funciones de otros paquetes, nos permiten hacer diferentes ajustes a la forma en cómo aparecen los datos en el gráfico:
Por ejemplo, etiquetas de categorías muy largas:
tabla2 <- prop.table(table(genero12$P32, genero12$SEXO), 2)*100
tabla2
##
## Masculino Femenino
## Hago mucho más de lo que me corresponde 9.393939 32.222222
## Hago algo más de lo que me corresponde 10.303030 29.722222
## Hago más o menos lo que me corresponde 45.454545 29.444444
## Hago algo menos de lo que me corresponde 15.757576 3.611111
## Hago mucho menos de lo que me corresponde 13.333333 2.500000
## No contesta 5.757576 2.500000
tabla2 <- as.data.frame(tabla2)
ggplot(data= tabla2, aes(x=Var1, y=Freq, fill = Var2)) +
geom_bar(stat = "identity", position = position_dodge(), color = "black") +
xlab(" ") + ylab("%") + scale_fill_brewer(name = "Sexo", palette = "Greys") +
labs(title = "¿Cuál de las frases siguientes describe mejor la forma en que se reparten \nlas tareas domésticas Ud. y su pareja?, según sexo del entrevistado", subtitle = "% según el sexo del entrevistado") + theme_bw()
# Se puede justificar una etiqueta muy larga usando una función del paquete stringr
library(stringr)
ggplot(data= tabla2, aes(x=Var1, y=Freq, fill = Var2)) +
geom_bar(stat = "identity", position = position_dodge(), color = "black") +
scale_x_discrete(labels = function(x) str_wrap(x, width = 10)) +
xlab(" ") + ylab("%") + scale_fill_brewer(name = "Sexo", palette = "Greys") +
labs(title = "¿Cuál de las frases siguientes describe mejor la forma en que se reparten \nlas tareas domésticas Ud. y su pareja?, según sexo del entrevistado", subtitle = "% según el sexo del entrevistado") + theme_bw()
Existen múltiples opciones usar y elementos que podemos añadir a un gráfico en ggplot para que quede exactamente como queremos que se vea. Un buen lugar donde pueden explorarse varias de esas opciones es la página de gráficos de R Graphics Cookbook que se recomienda revisar al momento de trabajar con gráficos en ggplot.
Para exportar un gráfico podemos grabarlo como un archivo en formato png, lo que nos permite insertarlo en un documento como Word. El comando ggsave nos permite varios ajustes (alto, ancho, calidad) para el archivo gráfico final.
# Guardamos el gráfico como objeto en R:
grafico1 <- ggplot(data= tabla2, aes(x=Var1, y=Freq, fill = Var2)) +
geom_bar(stat = "identity", position = position_dodge(), color = "black") +
scale_x_discrete(labels = function(x) str_wrap(x, width = 10)) +
xlab(" ") + ylab("%") + scale_fill_brewer(name = "Sexo", palette = "Greys") +
labs(title = "¿Cuál de las frases siguientes describe mejor la forma en que se reparten \nlas tareas domésticas Ud. y su pareja?, según sexo del entrevistado", subtitle = "% según el sexo del entrevistado") + theme_bw()
# Grabamos el gráfico en formato png, en forma rectangular 8 x 6
ggsave(filename = "grafico1.png", grafico1, width = 8, height = 6)