El efecto de cada capa en gráficos ggplot

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.

true
07-09-2021

Visualizaciones con ggplot2 💫

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.

Librerías 📚

Se utilizan las siguientes librerías:

Audiencia de Mr Robot por episodio 💻

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:

Show code
# 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:

Show code
table {
  cursor: pointer; 
  cursor: hand;
  border: none;
  margin-left: auto;
  margin-right: auto;
  width:"80%";
  border:"0"; 
  cellspacing:"0"; 
  cellpadding:"0";
  font-family: "Lucida Console";
}

.hover {background-color: #b5ffc9;}

.image-crop {height: 600px;;}

tab1 { padding-left: 4em; }
tab2 { padding-left: 8em; }

.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 🌟:

Show code
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))+
geom_col(aes(fill=season))+
coord_polar(start = 0) + ylim(0,3)
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=angle)+
geom_text(data=label_data, aes(x=id, y=viewers+0.4,
label=Title,hjust=hjust), color=“black,”
fontface=“bold,” alpha=0.6, size=3,angle= label_data$angle)+
scale_fill_manual(values = c(“#325c38,” “#5b8f65,” “#87c595,”“#b5ffc9”)
theme_minimal()+
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))
labs(fill=“Temporada,” title=“Audiencia de Mr Robot,”
caption=“#30diasdegraficos Una iniciativa de R4DS_es”)+

Sin embargo, para html_output se utiliza {htmltools} 📦:

htmltools::HTML(resultado)

Comentarios finales 💬

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 🙌 🙌 🙌

Contacto ✉

Karina Bartolome Twitter Badge Linkedin Badge Github Badge Website Badge

Welle, Arthur. 2021. Codehover: Hoverable HTML Table for Displaying Intermediary Code Results (Pipes). https://github.com/arthurwelle/codehover.
Wickham, Hadley. 2020. Rvest: Easily Harvest (Scrape) Web Pages. https://CRAN.R-project.org/package=rvest.
Wickham, Hadley, Mara Averick, Jennifer Bryan, Winston Chang, Lucy D’Agostino McGowan, Romain François, Garrett Grolemund, et al. 2019. “Welcome to the tidyverse.” Journal of Open Source Software 4 (43): 1686. https://doi.org/10.21105/joss.01686.

  1. Wickham et al. (2019)↩︎

  2. Welle (2021)↩︎

  3. Wickham (2020)↩︎

References

Citation

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}
}