A lo largo de este documento, se buscará realizar una breve introducción a la visualización de datos con ggplot, con el complemento de otras librerías que nos permitan ordenar y transformar nuestra data cuando sea necesario para mejorar nuestros gráficos. Revisaremos funciones que nos facilitarán el trabajo de personalizar a nuestro antojo diferentes elementos estéticos, presentando solo una pincelada de las posibilidades que tidyverse nos entrega. En esa línea, este documento solo tiene pretensiones introductorias.
El documento esta estructurado de manera incremental, iniciando con una presentación de algunas de las geometrías que ggplot nos ofrece para la representación de diferentes tipos de variables, para luego ir introduciendo, sobre la base de algunos ejemplos, distintas posibilidades de modificaciones estéticas. Antes de empezar, será necesaria la instalación de las siguientes librerías.
library(haven)
library(tidyverse)
library(gridExtra)
library(magrittr)
Tidyverse corresponde a un conjunto de paquetes especialmente diseñados para trabajar con conjuntos de datos, con librerías específicas que facilitan las labores de limpieza, ordenamiento, transformación de la estructura de nuestras bases de datos, como también de la visualización. ggplot2 es uno de sus paquetes más conocidos, orientado específicamente a la creación de gráficas personalizadas.
A lo largo de este documento, abordaremos distintas funciones que ggplot nos ofrece, apoyándonos en otros paquetes de Tidyverse para la manipulación de nuestros objetos. En particular, recurriremos mayoritariamente a los paquetes dplyr y tidyr. El primero proporciona un conjunto de funciones que facilita la manipulación de datos. El segundo entrega herramientas para ordenar nuestra data.
Para el ejercicio, se utilizará la base de datos de la Encuesta Nacional de Uso del Tiempo (ENUT) 2015. Utilizaremos read_sav para importar la base de datos. La mayor parte de las variables corresponden a un objeto de clase haven_labelled, en la medida que cuentan, simultáneamente, con un código y una etiqueta. RStudio trabajará por defecto con el código. Para indicarle lo contrario, usaremos as_factor.
data_enut <- read_sav("raw/BASE_USUARIO_corregida.sav")
data_enut <- data_enut %>% as_factor()
Como todos los paquetes de tidyverse, ggplot posee una gramática propia orientada a facilitar la visualización de datos, pero requiere familiarizarse con ella.
Implica proporcionar un conjunto de datos, agregar mediante capas la geometría en la cual esperamos visualizar ese conjunto de datos y un conjunto de especificaciones estéticas.
Partiremos visualizando las alternativas que ofrece la función geom para la representación visual de los datos y las propiedades estéticas que podemos especificar mediante aes().
En primer lugar, revisaremos las diferentes geometrías para la representación de variables continuas, en gráficas que permiten visualizar solo una variable por gráfico.
En este caso, estamos trabajando con la variable tiempo total destinado al trabajo doméstico no remunerado para el propio hogar en el día de semana (tdnr_ds) de la base de datos cargada.
A continuación, revisaremos el tipo de gráfica que podemos generar usando geom_density, geom_area, geom_freqpoly y geom_histogram. Para facilitar el reconocimiento del gráfico que corresponde a cada una de esas geometrías, se usó la función ggtitle para indicarlo en el título de cada gráfica. Más adelante exploraremos otras maneras de asignar y modificar títulos.
Vamos a utilizar la función grid.arrange perteneciente al paquete gridExtra que permite organizar múltiples gráficas en un mismo output. El comando requiere, al menos, indicar el nombre de los objetos que le pedimos considerar (en este caso, el nombre que le asignaremos a cada gráfico) y definir la cantidad de columnas en las que queremos que disponga los gráficos, para ello utilizamos el atributo ncol = 2, en donde “2” corresponde a la cantidad de columnas que estamos solicitando.
plot_density <- data_enut %>% ggplot(aes(tdnr_ds)) %+% geom_density() %+% ggtitle("Geom_density")
plot_area <- data_enut %>% ggplot(aes(tdnr_ds)) %+% geom_area(stat = "bin") %+% ggtitle("Geom_area")
plot_freqpoly <- data_enut %>% ggplot(aes(tdnr_ds)) %+% geom_freqpoly() %+% ggtitle("Geom_freqpoly")
plot_histogram <- data_enut %>% ggplot(aes(tdnr_ds)) %+% geom_histogram() %+% ggtitle("Geom_histogram")
grid.arrange(plot_density,plot_area,plot_freqpoly,plot_histogram, ncol = 2)
Como vemos, con geom_density se puede observar la estimación de la densidad de kernel, y corresponde a una alternativa útil para observar la distribución de una variable continua.
geom_area corresponde a un análogo de gráfico de barras apiladas para variables continuas y se puede usar como la distribución varía a lo largo del eje x.
geom_freqpoly, por otro lado, permite visualizar la distribución de una variable continua. Opera dividiendo el eje x en bins y contando el número de observaciones para cada uno y presentando su frecuencia como líneas.
Finalmente, geom_histogram opera de la misma manera que geom_freqpoly, dividiendo el eje x en bins pero presentando su frecuencia en barras.
Cuando nos encontramos con variables que adoptan valores discretos, que pueden representar categorías, como por ejemplo el sexo del encuestado (hombre, mujer), el nivel educacional (educación básica, media, universitaria, etc.) o el nivel socio-económico.
Para visualizarlo, usaremos la función geom_bar.
Además, introduciremos el atributo estético fill, que debe especificarse al interior de aes(). Con este argumento, le estamos pidiendo que diferencia cada categoría de la variable indicada con colores distintos. En este caso, le asigna por defecto una tonalidad de rojo para hombres y una tonalidad de azul para mujeres. A su vez, para identificar correctamente a que corresponde cada color, genera una leyenda con etiquetas que se ubica, también por defecto, en el costado derecho de la gráfica. Ya veremos cómo modificar estos atributos.
plot_bar <- data_enut %>% ggplot(aes(c13_1_1, fill = c13_1_1)) %+% geom_bar(position = "dodge")
plot_bar
La mayor parte de las veces, lo que requerimos es representar visualmente dos variables. Cuando una de las variables es discreta y la otra continua, tenemos dos buenas alternativas: geom_boxplot y geom_violin.
Con geom_boxplot podemos visualizar de manera compacta la distribución de una variable continua, permitiendo visualizar estadísticos de resumen a través de la mediana, las bisagras y los bigotes, presentando puntualmente cada outlier.
Mientras que geom_violin corresponde a un diagrama de densidad reflejado que se muestra de manera similar a un diagrama de caja.
En este caso, veremos un ejemplo de cada uno. Para ello, utilizaremos el sexo del encuestado como nuestro eje x y en el eje y, la misma variable de tiempo total destinado al trabajo doméstico no remunerado que ya utilizamos.
Además, introduciremos nuevos atributos. En primer lugar, note que hemos asignado para cada gráfico también un subtítulo. Eso fue posible utilizando la función labs(subtitle = ). Pronto volveremos a ella para observar otras alternativas que nos ofrece.
En cada subtítulo indicamos las especificaciones estéticas introducidas a cada gráfico. Ya habíamos comentado respecto al atributo fill que utilizamos para el boxplot. Ahora, también introducimos el atributo colour. Notese las diferencias. En este último caso, solo se colorea el borde de la figura.
#Geom_boxplot
plot_boxplot <- data_enut %>% ggplot(aes(c13_1_1,tdnr_ds, fill = c13_1_1)) #Identificar data y atributos esteticos
plot_boxplot <- plot_boxplot %+% geom_boxplot() #Definir geometría
plot_boxplot <- plot_boxplot %+% ggtitle("Geom_boxplot") #Asignar titulo
plot_boxplot <- plot_boxplot %+% labs(subtitle = "aes(x, y, fill)") #Atributo Fill
#Geom_violin
plot_violin <- data_enut %>% ggplot(aes(c13_1_1,tdnr_ds, colour = c13_1_1)) #Identificar data y atributos esteticos
plot_violin <- plot_violin %+% geom_violin() #Definir geometría
plot_violin <- plot_violin %+% ggtitle("Geom_violin") #Asignar titulo
plot_violin <- plot_violin %+% labs(subtitle = "aes(x, y, colour)") #Atributo colour
#Plotear en conjunto
grid.arrange(plot_boxplot, plot_violin, ncol = 2)
También pudiésemos querer visualizar dos variables continuas. En ese caso, podemos utilizar geom_point o geom_jitter.
Con geom_point podemos crear diagramas de dispersión, que son útiles para visualizar la relación entre dos variables continuas.
Por otro lado, geom_jitter se le agrega una pequeña cantidad de ruido aleatorio a datos que se encuentran sobreplotados, lo que será útil cuando los puntos se encuentran rodeados de espacio en blanco.
Para nuestro eje x, agregaremos el ingreso por el trabajo, que corresponde a la suma de trabajo principal más el de segundas ocupaciones, calculada a nivel persona. En el eje y, se utiliza el tiempo total destinado al trabajo doméstico no remunerado en días de semana.
Con la función geom_hline podemos incorporar una línea horizontal, indicando en qué punto del eje y queremos que nazca dicha línea con el atributo estético yintercept. En este caso, estamos instalando la línea en el punto en que la cantidad de horas dedicadas al trabajo doméstico no remunerado en día de semana es igual a 15 horas, quedando sobre la línea la cantidad de casos que dedica más de 15 horas a esas labores en días de semana y bajo la línea quienes dedican menos de 15 horas.
De la misma manera, con geom_vline podemos agregar líneas verticales. Para ello, utilizaremos xintercept para señalar el punto en el que línea se encuentra con el eje x, que en este caso, corresponde al ingreso producto del trabajo. Le señalamos que lo haga en x = $500.000, quedando a un lado quienes declaran ingresos menores y al otro lado quienes declaran ingresos mayores. Con el comando size se puede modificar el grosor de la línea.
#Geom_point
plot_point <- data_enut %>% ggplot(aes(ing_trab,tdnr_ds)) #Identificar data y atributos esteticos
plot_point <- plot_point %+% geom_point() #Definir geometría
plot_point <- plot_point %+% ggtitle("geom_point") #Asignar titulo
#Geom_jitter con geom_hline
plot_jitter <- data_enut %>% ggplot(aes(ing_trab,tdnr_ds)) #Identificar data y atributos esteticos
plot_jitter <- plot_jitter %+% geom_jitter() #Definir geometría
plot_jitter <- plot_jitter %+% ggtitle("geom_jitter con geom_hline") #Asignar titulo
plot_jitter <- plot_jitter %+% geom_hline(aes(yintercept = 15, color = "red")) #Plotear linea horizontal de color rojo
#Geom_jitter con geom_vline
plot_jitter_1 <- data_enut %>% ggplot(aes(ing_trab,tdnr_ds)) #Identificar data y atributos esteticos
plot_jitter_1 <- plot_jitter_1 %+% geom_jitter() #Definir geometría
plot_jitter_1 <- plot_jitter_1 %+% ggtitle("geom_jitter con geom_vline") #Asignar titulo
plot_jitter_1 <- plot_jitter_1 %+% geom_vline(aes(xintercept = 500000, color = "red", size = 2)) #Plotear linea horizontal de color azul y mayor tamaño
grid.arrange(plot_point,plot_jitter,plot_jitter_1, ncol = 2)
Continuando con el ejemplo anterior, probablemente quisiéramos incorporar información respecto a que significa estar sobre o bajo la línea, incorporando texto o símbolos que permita clarificarlo en la misma gráfica.
Para ello, utilizaremos una nueva función annotate que nos permitirá agregar como capa nuevos elementos, lo que en este caso utilizaremos para incorporar flechas a ambos lados de la línea horizontal que separa a quienes dedican más de 15 horas al trabajo doméstico durante un día de semana respecto a quienes dedican menos de ello. Al interior de annotate definiremos el texto que queremos agregar con label, el tamaño de la letra size y donde queremos ubicarlo, señalando las coordenadas x,y.
Con esta misma modalidad, podemos plotear toda clase de símbolos, utilizando sus respectivos códigos unicode.
plot_jitter <- plot_jitter %+% annotate(geom = "text", x=1.5e+07,y=17,label="Más de 15 horas",size=3) #Se agrega texto
plot_jitter <- plot_jitter %+% annotate(geom = "text", x=1.3e+07,y=17, label= sprintf("\U2191"), color = "red", size = 8) #Agregar flecha hacia arriba con código unicode
plot_jitter <- plot_jitter %+% annotate(geom = "text", x=1.5e+07,y=13,label="Menos de 15 horas",size=3) #Se agrega texto
plot_jitter <- plot_jitter %+% annotate(geom = "text", x=1.3e+07,y=13, label= sprintf("\U2193"), color = "red", size = 8) #Agregar flecha hacia abajo con código unicode
plot_jitter
Hasta ahora, ya hemos revisado las principales geometrías de ggplot para visualizar nuestros datos, sean estos variables continuas o categóricas. Hemos visto como modificar algunos de los atributos estéticos para personalizar nuestros gráficas pero aún queda camino para elaborar un gráfico que podamos presentar en un informe.
Antes de continuar, introduciremos un conjunto de funciones del paquete dplyr, que nos serán útiles para lo que viene por delante. Nos referimos a los siguientes verbos:
mutate permite crear nuevas variables en nuestro data.frame, computando transformaciones en variables existentes.
filter podemos aplicar filtros para seleccionar casos que cumplan una condición indicada.
select nos permitirá seleccionar un conjunto especifico de variables de nuestra data, permitiendo trabajar con un subconjunto de columnas del data.frame.
group_by permite agrupar un conjunto de observaciones en función de sus valores en alguna columna, lo que será útil para computar estadísticos de resumen a nivel de grupo.
Esta no corresponde a una lista exhaustiva del conjunto de verbos de dplyr, pero son los que nos serán útiles para la construcción de nuestras gráficas en el resto de este documento.
Así, en este caso volveremos a visualizar la relación entre el ingreso total producto del trabajo y el tiempo de trabajo destinado a trabajo doméstico no remunerado en días de semana con un geom_jitter, tal como lo hicimos anteriormente. Sin embargo, en esta oportunidad usaremos mutate para transformar la variable de ingresos usando logaritmo log.
#Geom_jitter
data_enut_1 <- data_enut %>% mutate(ingreso_log = log(ing_trab)) #Computar nueva variable
plot_jitter_1 <- data_enut_1 %>% ggplot(aes(ingreso_log,tdnr_ds)) #Identificar data y atributos esteticos
plot_jitter_1 <- plot_jitter_1 %+% geom_jitter() #Definir geometría
plot_jitter_1 <- plot_jitter_1 %+% ggtitle("Geom_jitter") #Agregar título
#Geom_boxplot
data_enut_2 <- data_enut %>% mutate(ingreso_log = log(ing_trab)) #Computar nueva variable
plot_boxplot_1 <- data_enut_2 %>% ggplot(aes(c13_1_1,ingreso_log)) #Identificar data y atributos esteticos
plot_boxplot_1 <- plot_boxplot_1 %+% geom_boxplot() #Definir geometría
plot_boxplot_1 <- plot_boxplot_1 %+% ggtitle("Geom_boxplot") #Agregar título
grid.arrange(plot_jitter_1,plot_boxplot_1, ncol = 2)
Asimismo, podemos usar filter para trabajar con un subconjunto de casos que cumpla una determinada condición. Por ejemplo, usaremos dicha función para visualizar el tiempo destinado por hombres y mujeres al trabajo doméstico no remunerado en días de semana, filtrando en gráficos diferentes para cada quintil de trabajo. Esto implica que cada gráfico presenta los resultados correspondientes a un determinado quintil de trabajo.
#Primer quintil
data_enut_1 <- data_enut %>% filter(quintil == 1) #Filtrar casos quintil = 1
plot_enut_1 <- data_enut_1 %>% ggplot(aes(c13_1_1,tdnr_ds)) #Identificar data y variables
plot_enut_1 <- plot_enut_1 %+% geom_boxplot() #Definir geometría
plot_enut_1 <- plot_enut_1 %+% ggtitle("Primer quintil") #Asignar titulo
#Segundo quintil
data_enut_2 <- data_enut %>% filter(quintil == 2) #Filtrar casos quintil = 2
plot_enut_2 <- data_enut_2 %>% ggplot(aes(c13_1_1,tdnr_ds)) #Identificar data y variables
plot_enut_2 <- plot_enut_2 %+% geom_boxplot() #Definir geometría
plot_enut_2 <- plot_enut_2 %+% ggtitle("Segundo quintil") #Asignar titulo
#Tercer quintil
data_enut_3 <- data_enut %>% filter(quintil == 3) #Filtrar casos quintil = 3
plot_enut_3 <- data_enut_3 %>% ggplot(aes(c13_1_1,tdnr_ds)) #Identificar data y variables
plot_enut_3 <- plot_enut_3 %+% geom_boxplot() #Definir geometría
plot_enut_3 <- plot_enut_3 %+% ggtitle("Tercer quintil") #Asignar titulo
#Cuarto quintil
data_enut_4 <- data_enut %>% filter(quintil == 4) #Filtrar casos quintil = 4
plot_enut_4 <- data_enut_4 %>% ggplot(aes(c13_1_1,tdnr_ds)) #Identificar data y variables
plot_enut_4 <- plot_enut_4 %+% geom_boxplot() #Definir geometría
plot_enut_4 <- plot_enut_4 %+% ggtitle("Cuarto quintil") #Asignar titulo
#Quinto quintil
data_enut_5 <- data_enut %>% filter(quintil == 5) #Filtrar casos quintil = 5
plot_enut_5 <- data_enut_5 %>% ggplot(aes(c13_1_1,tdnr_ds)) #Identificar data y variables
plot_enut_5 <- plot_enut_5 %+% geom_boxplot() #Definir geometría
plot_enut_5 <- plot_enut_5 %+% ggtitle("Quinto quintil") #Asignar titulo
grid.arrange(plot_enut_1,plot_enut_2,plot_enut_3,plot_enut_4,plot_enut_5, ncol = 3)
facets corresponde a la definición de grupos de facetas, que se presentarán de manera ordenada en una matriz de filas y columnas.
Con facet_grid podemos formar una matriz de paneles, que permite visualizar en gráficos diferentes cada nivel de una variable categórica: en este caso, el quintil de ingresos al que pertenece cada encuestado.
#Facet_grid
plot_facet_1 <- data_enut %>% ggplot(aes(c13_1_1,tdnr_ds))
plot_facet_1 <- plot_facet_1 %+% geom_boxplot()
plot_facet_1 <- plot_facet_1 %+% facet_grid(~quintil)
plot_facet_1
Por otro lado, con facet_wrap podemos ver también una secuencia de paneles, que se nos presentan por defecto de manera rectangular en dos filas. La cantidad de filas y columnas puede ser definida por el usuario.
#Facet_wrap
plot_facet_2 <- data_enut %>% ggplot(aes(c13_1_1,tdnr_ds))
plot_facet_2 <- plot_facet_2 %+% geom_boxplot()
plot_facet_2 <- plot_facet_2 %+% facet_wrap(.~quintil)
plot_facet_2
Hemos revisado detenidamente diferentes posibilidades que tidyverse nos entrega para manipular y representar nuestros datos. Pero aún hay más.
Muchas veces, nos vamos a encontrar con algunas limitaciones para construir los gráficos que quisiéramos con la estructura actual de nuestro data frame. Por ejemplo, si en un gráfico de barras quisiéramos plotear la proporción de casos que representa cada categoría, una forma fácil de hacerlo sería crear una variable de frecuencia que no existe en nuestro data frame actual. Además, como en este caso, puede que estemos trabajando con una base de datos que contenga ponderadores o factores de expansión, y queremos que nuestras visualizaciones estén representando adecuadamente dicha información.
Para enfrentar estos desafíos, requeriremos transformar nuestra data para representar mejor nuestros datos. Y si bien, pueden existir muchas formas de hacerlo, en este caso solo recurriremos a las herramientas que nos entregan los paquetes que conforman tidyverse.
Para el siguiente ejemplo, vamos a construir un data.frame que nos presente la proporción de casos según nivel educacional, ponderando los resultados según el ponderador wgt2 que trae la propia base de datos.
En esta oportunidad, recurriremos a tres nuevas funciones: count, wt y sum.
data_sexo_participa <- data_enut %>% filter(p_tdnr_ds %>% is.na %>% not)
data_sexo_participa <- data_sexo_participa %>% group_by(c13_1_1)
data_sexo_participa <- data_sexo_participa %>% count(p_tdnr_ds, wt = wgt2)
data_sexo_participa <- data_sexo_participa %>% mutate(total = sum(n))
data_sexo_participa <- data_sexo_participa %>% mutate(proporcion = n/total)
data_sexo_participa <- data_sexo_participa %>% ungroup()
data_sexo_participa <- data_sexo_participa %>% mutate(total_n = sum(n))
knitr::kable(data_sexo_participa)
| c13_1_1 | p_tdnr_ds | n | total | proporcion | total_n |
|---|---|---|---|---|---|
| Hombre | No participa | 1104025.3 | 6192121 | 0.1782952 | 12980639 |
| Hombre | Participa | 5088096.1 | 6192121 | 0.8217048 | 12980639 |
| Mujer | No participa | 486448.8 | 6788518 | 0.0716576 | 12980639 |
| Mujer | Participa | 6302068.7 | 6788518 | 0.9283424 | 12980639 |
Nuestro nuevo data.frame contiene la proporción de casos que afirma participar o no del trabajo doméstico en día de semana según sexo. En ello nos permitirá construir gráficas donde dicha proporción pueda plotearse como un elemento estético en el gráfico.
Para ello, utilizaremos nuevamente función geom_text que nos permitirá agregar como capa nuevos elementos, lo que en este caso utilizaremos para incorporar sobre cada barra el porcentaje de casos que representa. Al interior de geom_text utilizaremos aes() para definir que es lo que queremos agregar y donde queremos ubicarlo.
De esta manera, le indicaremos las coordenadas x e y en las que queremos agregar este nuevo elemento, y luego usamos label para indicar que el nuevo elemento corresponde a la columna proporcion de nuestro data.frame multiplicada por 100, para presentarlo como porcentaje. Con la función round le solicitamos que dicha proporción sea redondeada, considerando solo un decimal.
El código se presenta a continuación:
plot_bar_2 <- data_sexo_participa %>% ggplot(aes(x = c13_1_1, y = proporcion, fill = p_tdnr_ds))
plot_bar_2 <- plot_bar_2 %+% geom_bar(stat="identity", position = position_dodge())
plot_bar_2 <- plot_bar_2 %+% geom_text(aes(x=c13_1_1,y=proporcion,label = paste0(round(proporcion*100,1),"%")), position = position_dodge(width = 0.9), vjust=-1,size=3)
plot_bar_2
Para la modificación de títulos, subtítulos y caption, recurriremos a labs, la que nos permitirá introducir estos elementos a nuestro gráfico. A su vez, usaremos plot.title para modificar algunos atributos del título, en particular el tamaño de la letra con size y le indicaremos que lo presente en negrita, al especificar “bold” en face.
plot_bar_2 <- plot_bar_2 %+% labs(title = "Participación en trabajo doméstico en días de semana según sexo") #agregar titulo
plot_bar_2 <- plot_bar_2 %+% theme(plot.title = element_text(size = 13, face = "bold")) #modificar tamaño de titulo o agregar negrita
plot_bar_2 <- plot_bar_2 %+% labs(subtitle = "Datos de Encuesta Nacional de Uso del Tiempo (ENUT)") #Agregar subtitulo
plot_bar_2 <- plot_bar_2 %+% labs(caption = data_sexo_participa %>% select(total_n) %>% distinct %$% paste0("N = ", total_n %>% round)) #Agregar N de casos en la parte baja
plot_bar_2
En muchas oportunidades vamos a requerir modificar los ejes x e y de nuestro gráfico, además de la leyenda. Veremos cómo modificar diferentes parámetros estéticos asociados a ellos.
En primer lugar, vamos a modificar el nombre del eje x para reemplazar el nombre de la variable por una etiqueta que especifique que se trata del “Sexo del entrevistado”. Para ello, usaremos labs, a la que ya hemos recurrido anteriormente.
plot_bar_2 <- plot_bar_2 %+% labs(x = "Sexo del entrevistado") #cambiar nombre de eje
plot_bar_2
Si bien en este caso no resulta relevante, podríamos modificar también el tamaño o el color del título del eje x. Vamos a recurrir a theme que permite modificar y customizar diferentes componentes de la apariencia del gráfico, no relacionados con la data. En este caso, recurriremos a axis.title.x que nos permitirá modificar tamaño de letra y color de la letra del título del eje.
plot_bar_2_t <- plot_bar_2 %+% theme(axis.title.x = element_text(size = 20)) #modificar tamaño
plot_bar_2_t <- plot_bar_2_t %+% theme(axis.title.x = element_text(colour = "red")) #modificar color
plot_bar_2_t
Incluso, podríamos querer prescindir de dicho título, si nos parece que no aporta información relevante para la comprensión del gráfico. Para ello, le indicaremos que queremos prescindir del título del eje x axis.title.x con la función element_blank.
plot_bar_2_t <- plot_bar_2_t %+% theme(axis.title.x = element_blank()) #Eliminar título eje x
plot_bar_2_t
Para el caso del eje y, podemos realizar los mismos ajustes que los vistos anteriormente para el eje x. En este caso, vamos a partir por cambiarle el título al eje y ajustar su escala, para que el porcentaje sobre la barra de mujeres que participan de labores domésticas no quede cortado.
plot_bar_2_t <- plot_bar_2_t %+% labs(y = "Porcentaje (%)") #cambiar nombre de eje
plot_bar_2_t <- plot_bar_2_t %+% scale_y_continuous(limits = c(0,1)) #modificar escala de eje para que se mueva entre 0 y 1
plot_bar_2_t
También podríamos modificar el tamaño o el color del título del eje y. En este caso, recurriremos a axis.title.y que cumple función analoga a axis.title.x vistas anteriormente y que nos permitirá modificar tamaño de letra y color de la letra del título del eje.
plot_bar_2_y <- plot_bar_2_t %+% theme(axis.title.y = element_text(size = 20)) #modificar tamaño
plot_bar_2_y <- plot_bar_2_y %+% theme(axis.title.y = element_text(colour = "red")) #modificar color
plot_bar_2_y
Por último, podríamos querer eliminar los ticks y números que se observan en el eje y. Ello podemos hacerlo con axis.text.y para el primer caso, y axis.ticks.y para el segundo caso. En ambos, especificaremos element_blank para señalar que queremos prescindir de dichos elementos.
plot_bar_2_t <- plot_bar_2_t %+% theme(axis.text.y = element_blank()) #Elimina números del eje y
plot_bar_2_t <- plot_bar_2_t %+% theme(axis.ticks.y = element_blank()) #Elimina ticks
plot_bar_2_t
Asimismo, podríamos querer modificar las etiquetas de la leyenda. Como se observa en la gráfica anterior, mantiene por defecto el nombre de la variable en la data, que no resulta pertinente para identificar a que corresponde. Por ello, utilizaremos scale_fill_discrete que nos entrega herramientas para modificar nombre y etiquetas de la leyenda.
plot_bar_2_t <- plot_bar_2_t %+% scale_fill_discrete(name = "Participación", labels = c("No", "Si")) #Cambiar titulo y etiquetas de leyenda
plot_bar_2_t
Por último, ggplot ofrece una serie de theme que permiten customizar de manera automática diferentes componentes según plantillas pre-determinadas.
Por defecto, hemos estados utilizando theme_grey, pero ella no es la única. Obsérvense a modo de ejemplo las diferencias estéticas al reemplazarlo por theme_minimal.
plot_bar_2grey <- plot_bar_2_t %+% theme_grey() %+% labs(title = "Theme grey") %+% theme(plot.subtitle = element_blank())
plot_bar_2minimal <- plot_bar_2_t %+% theme_minimal() %+% labs(title = "Theme minimal") %+% theme(plot.subtitle = element_blank())
grid.arrange(plot_bar_2grey, plot_bar_2minimal, ncol = 2)
Otros ejemplos son theme_bw o theme_classic.
plot_bar_2bw <- plot_bar_2_t %+% theme_bw() %+% labs(title = "Theme bw") %+% theme(plot.subtitle = element_blank())
plot_bar_2classic <- plot_bar_2_t %+% theme_classic() %+% labs(title = "Theme classic") %+% theme(plot.subtitle = element_blank())
grid.arrange(plot_bar_2bw, plot_bar_2classic, ncol = 2)
Hemos ido viendo paso a paso como ir introduciendo diferentes ajustes estéticos a nuestros gráficos. A continuación, queremos resumir en varias líneas de código el camino que debiésemos recorrer para dar con una visualización atractiva.
#Transformar nuestra data
data_sexo_participa <- data_enut %>% filter(p_tdnr_ds %>% is.na %>% not) #Filtrar valores perdidos en la variable de interes
data_sexo_participa <- data_sexo_participa %>% group_by(c13_1_1) #Agrupar según sexo
data_sexo_participa <- data_sexo_participa %>% count(p_tdnr_ds, wt = wgt2) #Realizar un conteo ponderado de casos según la agrupación previa
data_sexo_participa <- data_sexo_participa %>% mutate(total = sum(n)) #Crear variable total de casos según agrupación previa
data_sexo_participa <- data_sexo_participa %>% mutate(proporcion = n/total) #Crear variable de proporción de casos según agrupación previa
data_sexo_participa <- data_sexo_participa %>% ungroup() #Deshacer la agrupación según sexo
data_sexo_participa <- data_sexo_participa %>% mutate(total_n = sum(n)) #Computar total de casos
#Definir geometria a utilizar
plot_bar_3 <- data_sexo_participa %>% ggplot(aes(x = c13_1_1, y = proporcion, fill = p_tdnr_ds)) #Identificar data y variables a utilizar
plot_bar_3 <- plot_bar_3 %+% geom_bar(stat="identity", position = position_dodge()) #Definir geometría
#Plotear porcentajes
plot_bar_3 <- plot_bar_3 %+% geom_text(aes(x=c13_1_1,y=proporcion,label = paste0(round(proporcion*100,1),"%")), position = position_dodge(width = 1), vjust=-1,size=3) #Plotear proporción de casos sobre cada barra
#Modificar titulos, ejes y leyendas
plot_bar_3 <- plot_bar_3 %+% labs(title = "Participación en trabajo doméstico según sexo") #Agregar titulo
plot_bar_3 <- plot_bar_3 %+% labs(subtitle = "Datos de Encuesta Nacional de Uso del Tiempo (ENUT)") #Agregar subtitulo
plot_bar_3 <- plot_bar_3 %+% labs(caption = data_sexo_participa %>% select(total_n)%>% distinct %$% paste0("N = ", total_n %>% round)) #Agregar cantidad de casos
plot_bar_3 <- plot_bar_3 %+% labs(y = "Porcentaje de casos (%)") #Modificar titulo eje y
plot_bar_3 <- plot_bar_3 %+% labs(x = "Sexo del entrevistado") #Modificar titulo eje x
plot_bar_3 <- plot_bar_3 %+% scale_y_continuous(limits = c(0,1)) #Modificar escala eje y
plot_bar_3 <- plot_bar_3 %+% scale_fill_discrete(name = "Participación", labels = c("No", "Si")) #Modificar leyenda
#Modificar theme
plot_bar_3 <- plot_bar_3 %+% theme_classic()
plot_bar_3
ggplot nos permite también modificar el sistema de coordenadas tradicional.
Una modificación a los sistemas de coordenadas se puede introducir con coord_polar, que se usa para generar gráficas circulares. Estos se asemejan a los gráficos de barras apilada, pero estableciendo coordenadas polares.
Para los ejemplos que revisaremos, utilizaremos la variable t11_1_1 que da cuenta del grado de satisfacción con el tiempo que cada entrevistado se dedica a sí mismo. Partiremos transformando la estructura de nuestro data.frame, de manera que sea más funcional a nuestro propósito. Lo haremos haciendo uso de las mismas funciones que ya hemos revisado en ejercicios anteriores.
#Transformar nuestra data
data_satisfaccion <- data_enut %>% filter(t11_1_1 %>% is.na %>% not) #Filtrar valores perdidos en la variable de interes
data_satisfaccion <- data_satisfaccion %>% count(t11_1_1, wt = wgt2) #Realizar un conteo ponderado
data_satisfaccion <- data_satisfaccion %>% mutate(total = sum(n)) #Crear variable total de casos
data_satisfaccion <- data_satisfaccion %>% mutate(proporcion = n/total) #Crear variable de proporción
data_satisfaccion <- data_satisfaccion %>% filter(t11_1_1 != 96) #Filtrar casos con dato perdido "96"
data_satisfaccion <- data_satisfaccion %>% filter(t11_1_1 != "No aplica") #Filtrar casos "No aplica"
Ya con la data con un formato que nos será útil, pasaremos a revisar la manera en que generar un gráfico de torta (pie chart) y un gráfico de donas (donut chart). Ambos serán especificados como un geom_bar, de manera previa a introducir coord_polar que indica que estamos solicitando que se represente visualmente con un sistema de coordenadas polares.
Nótese que en los atributos estéticos en aes(), en el lugar donde identificamos la variable a asignar al eje x, reemplazamos el nombre de la variable en cuestión por el número “2”. En cambio, con fill indicamos la variable que esperamos graficar.
Finalmente, la única diferencia entre ambos tipos de gráficas, corresponde a la función xlim(0.5,2.5) que incorporamos para el gráfico de donas, que genera el espacio en blanco en el centro del gráfico de torta.
#pie chart
plot_pie <- data_satisfaccion %>% ggplot(aes(x=2, y=proporcion, fill=t11_1_1))
plot_pie <- plot_pie %+% geom_bar(stat = "identity", position = position_stack(), width = 1)
plot_pie <- plot_pie %+% coord_polar("y")
plot_pie <- plot_pie %+% theme_void()
plot_pie <- plot_pie %+% ggtitle("Pie chart")
#donut chart
plot_donut <- data_satisfaccion %>% ggplot(aes(x=2, y=proporcion, fill=t11_1_1))
plot_donut <- plot_donut %+% geom_bar(stat = "identity", position = position_stack(), width = 1)
plot_donut <- plot_donut %+% coord_polar("y")
plot_donut <- plot_donut %+% xlim(0.5,2.5)
plot_donut <- plot_donut %+% theme_void()
plot_donut <- plot_donut %+% ggtitle("Donut chart")
grid.arrange(plot_pie, plot_donut, ncol = 2)
Finalmente, si aplicamos nuevamente el conjunto de funciones ya revisados, podemos modificar numerosos elementos estéticos para dejar nuestra visualización en un formato publicable como el siguiente.
#donut chart
plot_donut1 <- data_satisfaccion %>% ggplot(aes(x=2, y=proporcion, fill=t11_1_1)) #Identificar data y variables
plot_donut1 <- plot_donut1 %+% geom_bar(stat = "identity", position = position_stack(), width = 1) #Definir geometría
plot_donut1 <- plot_donut1 %+% coord_polar("y") #Sistema de coordenadas polar
plot_donut1 <- plot_donut1 %+% xlim(0.5,2.5) #Generar gráfico dona
plot_donut1 <- plot_donut1 %+% theme_void() #Definir theme
#Plotear porcentajes
plot_donut1 <- plot_donut1 %+% geom_text(aes(label= paste0(round(proporcion*100,1),"%" )), position=position_stack(vjust = 0.5), size = 3) #Incorporar porcentajes
#Modificar titulos, ejes y leyendas
plot_donut1 <- plot_donut1 %+% labs(title = "Satisfacción con el tiempo que se dedica a si mismo") #Agregar titulo
plot_donut1 <- plot_donut1 %+% labs(subtitle = "Datos de Encuesta Nacional de Uso del Tiempo (ENUT)") #Agregar subtitulo
plot_donut1 <- plot_donut1 %+% labs(caption = data_sexo_participa %>% select(total_n)%>% distinct %$% paste0("N = ", total_n %>% round)) #Agregar cantidad de casos
plot_donut1 <- plot_donut1 %+% scale_fill_discrete(name = "") #Borrar título de leyenda
#Plotear gráfico
plot_donut1
En este caso, trabajaremos con coord_flip que nos permite voltear las coordenadas de manera, de manera que el eje horizontal se presente como vertical, y el eje vertical como horizontal.
#Transformar nuestra data
data_educacion <- data_enut %>% filter(d12_1_1 %>% is.na %>% not) #Filtrar valores perdidos en la variable de interes
data_educacion <- data_educacion %>% count(d12_1_1, wt = wgt2) #Realizar un conteo ponderado
data_educacion <- data_educacion %>% mutate(total = sum(n)) #Crear variable total de casos
data_educacion <- data_educacion %>% mutate(proporcion = n/total) #Crear variable de proporción
data_educacion <- data_educacion %>% filter(d12_1_1 != 96) #Filtrar casos con dato perdido "96"
plot_flip <- data_educacion %>% ggplot(aes(x = d12_1_1, y = proporcion)) #Identificar data y variables
plot_flip <- plot_flip %+% geom_bar(stat="identity", position = position_stack(), width=0.5) #Definir geometría
plot_flip <- plot_flip %+% coord_flip() #Barras Horizontales desde el eje y
plot_flip
Cuando se trata de categorías ordinales en donde existe un claro orden de jerarquía entre cada uno de los niveles, es recomendable que la gráfica mantenga ese orden. Este es el caso de nivel educacional, donde resulta natural ordenarlos según grado académico.
En el gráfico anterior, nos presenta los factores ordenados por defecto desde el código más alto al más pequeño, o lo que es lo mismo, desde el nivel educacional más alto al más bajo.
Sin embargo, podríamos querer invertir el orden, y presentar la información en orden inverso: desde el más bajo al más alto. fct_rev nos permitirá dicho cambio.
plot_flip_1 <- data_educacion %>% ggplot(aes(x = fct_rev(d12_1_1), y = proporcion)) #Identificar data y variables
plot_flip_1 <- plot_flip_1 %+% geom_bar(stat="identity", position = position_stack(), width=0.5) #Definir geometría
plot_flip_1 <- plot_flip_1 %+% coord_flip() #Barras Horizontales desde el eje y
plot_flip_1
No obstante lo dicho anteriormente, si quisiéramos presentar los factores ordenados por proporción, ya sea de mayor a menor o de menor a mayor. Para ambos casos, podemos recurrir a reorder, que nos permitirá organizar los factores según su proporción.
plot_flip_2 <- data_educacion %>% ggplot(aes(x = reorder(d12_1_1,proporcion), y = proporcion)) #Identificar data y variables
plot_flip_2 <- plot_flip_2 %+% geom_bar(stat="identity", position = position_stack(), width=0.5) #Definir geometría
plot_flip_2 <- plot_flip_2 %+% coord_flip() #Barras Horizontales desde el eje y
plot_flip_2
Por otro lado, para presentarlos ordenados de menor a mayor, recurrimos nuevamente a reorder pero anteponiendo el símbolo “-” a la variable proporción, indicando que los ordene de menor a mayor.
plot_flip_3 <- data_educacion %>% ggplot(aes(x = reorder(d12_1_1,-proporcion), y = proporcion)) #Identificar data y variables
plot_flip_3 <- plot_flip_3 %+% geom_bar(stat="identity", position = position_stack(), width=0.5) #Definir geometría
plot_flip_3 <- plot_flip_3 %+% coord_flip() #Barras Horizontales desde el eje y
plot_flip_3
Luego, si aplicamos el conjunto de funciones ya revisados previamente, podemos modificar numerosos elementos estéticos para dejar nuestra visualización en un formato publicable.
Por ejemplo, seguir el código que se presenta a continuación.
plot_flip <- data_educacion %>% ggplot(aes(x = d12_1_1, y = proporcion)) #Identificar data y variables
plot_flip <- plot_flip %+% geom_bar(stat="identity", position = position_stack(), width=0.5) #Definir geometría
#Plotear porcentajes
plot_flip <- plot_flip %+% geom_text(aes(x=d12_1_1,y=proporcion,label = paste0(round(proporcion*100,1),"%")), position = position_dodge(width = 0.9),hjust=-.8,vjust = .3,size=3) #Plotear proporción de casos sobre cada barra
#Modificar titulos, ejes y leyendas
plot_flip <- plot_flip %+% labs(title = "Nivel educacional de encuestado/as") #Agregar titulo
plot_flip <- plot_flip %+% labs(subtitle = "Datos de Encuesta Nacional de Uso del Tiempo (ENUT)") #Agregar subtitulo
plot_flip <- plot_flip %+% labs(caption = data_sexo_participa %>% select(total_n)%>% distinct %$% paste0("N = ", total_n %>% round)) #Agregar cantidad de casos
plot_flip <- plot_flip %+% scale_y_continuous(limits = c(0,1)) #Modificar escala eje y
#Theme
plot_flip <- plot_flip %+% theme_classic()
plot_flip <- plot_flip %+% theme(axis.title.x = element_blank()) #Eliminar título de eje y
plot_flip <- plot_flip %+% theme(axis.title.y = element_blank()) #Eliminar título de eje x
#Sistema de coordenadas
plot_flip <- plot_flip %+% coord_flip() #Barras Horizontales desde el eje y
plot_flip
Hasta aquí, hemos revisado una serie de funciones que nos permitirán construir gráficos visualmente atractivos y con información auto-contenida, para facilitar su interpretación por parte de los usuarios. Para ello, recorrimos diferentes librerías, principalmente pertenecientes a tidyverse. Para los diversos desafíos que aquí abordamos podemos encontrar otra forma de resolverlos, pero las herramientas presentadas serán un primer gran paso.