Ggplot se basa en añadir capas a un mismo objeto. En este artículo se utiliza el paquete codehover para visualizar qué efecto tiene cada capa sobre el gráfico final.
El paquete {ggplot2} 📦 del ecosistema {tidyverse}1 permite realizar visualizaciones avanzadas en un formato ordenado mediante capas. {codehover}2 📦 sirve para descomponer un gráfico ggplot en múltiples capas para entender cómo influye cada una sobre la visualización final.
Se utilizan las siguientes librerías:
Como ejemplo, utilizo una visualización que realicé para la iniciativa #30DiasDeGraficos:
Diagrama de Florence Nightingale: audiencia de Mr Robot por episodio. Gracias a las coordenadas polares se puede ver el episodio 1 “eps1.0_hellofriend.mov” al lado del final “Hello, Elliot” y me encanta ese contraste#30diasdegraficos, una iniciativa de (R4DS_es?) pic.twitter.com/JkUCVNabcl
— Karina Bartolomé 💚 ((karbartolome?)) June 10, 2020
Se obtienen los datos de Wikipedia con {rvest}3📦, un paquete para realizar web scraping siguiendo la lógica del enfoque tidy.
# Wikipedia:
url <- 'https://en.wikipedia.org/wiki/List_of_Mr._Robot_episodes#Ratings'
audiencia <- read_html(url)
# Dataframe a partir de las tablas de audiencia por episodio:
df <- bind_rows(
audiencia %>% html_nodes("table") %>% .[[8]] %>%
html_table(fill = TRUE) %>% mutate(season = 1),
audiencia %>% html_nodes("table") %>% .[[9]] %>%
html_table(fill = TRUE) %>% mutate(season = 2),
audiencia %>% html_nodes("table") %>% .[[10]] %>%
html_table(fill = TRUE) %>% mutate(season = 3),
audiencia %>% html_nodes("table") %>% .[[11]] %>%
html_table(fill = TRUE) %>% mutate(season = 4)
) %>%
# Obtener los viewers
separate(col = `Viewers(millions)`,
into = c("viewers", "remove"), sep='\\[') %>%
select(-remove) %>%
mutate(id = row_number(),
Title=gsub('"','',Title),
viewers = as.numeric(viewers),
season = as.factor(season))
# Ángulos de rotación para el gráfico
label_data <- df
number_of_bar <- nrow(label_data)
angle <- 90 - 360 * (df$id-0.5) /number_of_bar
label_data$hjust<-ifelse( angle < -90, 1, 0)
label_data$angle<-ifelse(angle < -90, angle+180, angle)
df <- df %>% mutate(id=as.factor(id))
👉Se generan las partes del gráfico a mostrar y se almacenan como imágenes.
height = 6
width = 7
# Primer gráfico:
g <- ggplot(df, aes(x = id, y = viewers)) +
geom_col(aes(fill = season))
ggplot2::ggsave("./IMG_caso1/1.png",
width = width, height = height, dpi = 100)
Sobre el gráfico g original se añaden nuevas capas, guardando cada nueva imagen en la carpeta de imágens:
# Se suma una capa de coordenadas polares:
g <- g + coord_polar()+ ylim(0,3)
ggplot2::ggsave("./IMG_caso1/2.png",
width = width, height = height, dpi = 100)
# Se suman 2 capas, una del texto de audiencia, otra del nombre de episodio:
g <- g + geom_text(data=label_data,
aes(x=id,
y=viewers+0.1,
label=paste0(round(viewers,1),"M"),
hjust=hjust),
color="red", fontface="bold",alpha=0.6,
size=2, angle= label_data$angle)
ggplot2::ggsave("./IMG_caso1/3.png",
width = width, height = height, dpi = 100)
g <- g + geom_text(data=label_data, aes(x=id,
y=viewers+0.4,
label=paste(Title),
hjust=hjust),
color="black", fontface="bold",alpha=0.6, size=3,
angle= label_data$angle)
ggplot2::ggsave("./IMG_caso1/4.png",
width = width, height = height, dpi = 100)
# Se suma una capa de colores:
g <- g + scale_fill_manual(values = c("#325c38", "#5b8f65",
"#87c595","#b5ffc9"))
ggplot2::ggsave("./IMG_caso1/5.png",
width = width, height = height, dpi = 100)
# Se suma una capa de theme_minimal()
g <- g + theme_minimal()
ggplot2::ggsave("./IMG_caso1/6.png",
width = width, height = height, dpi = 100)
# Se suma la capa de theme personalizado:
g <- g + theme(
axis.text = element_blank(),
axis.title = element_blank(),
panel.grid = element_blank(),
text=element_text(size=20, family="Andale Mono"),
legend.direction = 'horizontal',
legend.position = c(0.5,0.05),
plot.title=element_text(hjust=0.5)
)
ggplot2::ggsave("./IMG_caso1/7.png",
width = width, height = height, dpi = 100)
# Se añaden labels:
g <- g + labs(fill='Temporada',
title='Audiencia de Mr Robot',
caption='#30diasdegraficos \n Una iniciativa de @R4DS_es')
ggplot2::ggsave("./IMG_caso1/8.png",
width = width, height = height, dpi = 100)
📝Se incluye un código css para el formato del output:
table {cursor: pointer;
cursor: hand;
border: none;
margin-left: auto;
margin-right: auto;
width:"80%";
border:"0";
"0";
cellspacing:"0";
cellpadding:font-family: "Lucida Console";
}
.hover {background-color: #b5ffc9;}
.image-crop {height: 600px;;}
padding-left: 4em; }
tab1 { padding-left: 8em; }
tab2 {
.column {
float: left;
width: 50%;
padding: 10px;
margin-left: 10px;
width: 100%;
}
Siguiendo la documentación del paquete {codehover}, también es necesario incluir un .txt de javascript:
Se utilizan las funciones de {codehover} para generar el código html necesario para la visualización final 🌟:
Se inicializa la tabla html mediante ch_init()
Se añade cada una de las capas generadas como imágenes mediante la función ch_row()
Se indica la imagen asociada a la tabla html (en este caso, la primera)
resultado <- ch_int(type = "incremental", div_tag_add = "class='column'") %>%
ch_row(img = "./IMG_caso1/1.png",
text = "<div>ggplot(df, aes(x=id, y=viewers))+
<br> <tab1>geom_col(aes(fill=season))+</br></tab1>
</div>") %>%
ch_row(img = "./IMG_caso1/2.png",
text = "<div>coord_polar(start = 0) + ylim(0,3)</div>") %>%
ch_row(img = "./IMG_caso1/3.png",
text = '<div>geom_text(data=label_data, aes(x=id, y=viewers+0.1,
<br><tab1>label=paste0(round(viewers,1),"M"),hjust=hjust),</br></tab1>
<tab1>color="red", fontface="bold",alpha=0.6, </tab1>
<tab1>size=2,angle=angle)+</tab1></div>') %>%
ch_row( img = "./IMG_caso1/4.png",
text ='<div>geom_text(data=label_data,
<br><tab1>aes(x=id, y=viewers+0.4, label=Title,hjust=hjust),</br><tab1>
<tab1> color="black", fontface="bold",alpha=0.6, size=3,</tab1>
<tab1>angle= label_data$angle)+</tab1></div>') %>%
ch_row(img = "./IMG_caso1/5.png",
text = '<div>scale_fill_manual(
<br><tab1>values = c("#325c38", "#5b8f65", "#87c595","#b5ffc9")</br></tab1>
</div>') %>%
ch_row(img = "./IMG_caso1/6.png",
text = '<div>theme_minimal()+</div>') %>%
ch_row(img = "./IMG_caso1/7.png",
text = '<div>theme(axis.text = element_blank(),
<br><tab1>axis.title = element_blank(),</br><tab1>
<tab1>panel.grid = element_blank(),</tab1>
<tab1>text=element_text(size=20,family="Andale Mono"),</tab1>
<tab1>legend.direction = "horizontal", </tab1>
<tab1>legend.position = c(0.5,0.05),</tab1>
<tab1>plot.title=element_text(hjust=0.5))</tab1>
</div>') %>%
ch_row(img = "./IMG_caso1/8.png",
text = '<div>labs(fill="Temporada", title="Audiencia de Mr Robot",
<br><tab1>caption="#30diasdegraficos \n Una iniciativa de R4DS_es")+</br></tab1>
</div>') %>%
ch_out(img = "./IMG_caso1/1.png", div_tag_add = " class='column'")
⚠️ Al estar realizando un artículo distill, fue necesario visualizar el output generado mediante código inline:
`r resultado`
ggplot(df, aes(x=id, y=viewers))+
|
coord_polar(start = 0) + ylim(0,3)
|
geom_text(data=label_data, aes(x=id, y=viewers+0.1,
|
geom_text(data=label_data, aes(x=id, y=viewers+0.4,
|
scale_fill_manual(values = c(“#325c38,” “#5b8f65,” “#87c595,”“#b5ffc9”)
|
theme_minimal()+
|
theme(axis.text = element_blank(), axis.title = element_blank(),
|
labs(fill=“Temporada,” title=“Audiencia de Mr Robot,”
|
Sin embargo, para html_output se utiliza {htmltools} 📦:
htmltools::HTML(resultado)
Visualizar el efecto de cada una de las capas sobre un gráfico permite entender cómo funciona {ggplot2} y puede ser muy útil en ámbitos educativos 📚. Espero poder incorporar otros gráficos a este artículo.
👉 Actualmente {codehover} funciona muy bien para output: html_document. Sin embargo, en distill_article por ahora no encontré forma de generar el output en dos columnas (una código y otra para el gráfico).
Cualquier comentario es bienvenido 🙌 🙌 🙌
For attribution, please cite this work as
Bartolomé (2021, July 9). Karina Bartolome: El efecto de cada capa en gráficos ggplot. Retrieved from https://karbartolome-blog.netlify.app/posts/codehover-viz/
BibTeX citation
@misc{bartolomé2021el, author = {Bartolomé, Karina}, title = {Karina Bartolome: El efecto de cada capa en gráficos ggplot}, url = {https://karbartolome-blog.netlify.app/posts/codehover-viz/}, year = {2021} }