Search code examples
rimageplotly

Embed images in plotly tick labels


I would like to embed images as part of x axis in a plotly chart (not in place of x axis). Code of what I have tried:

library(plotly)
library(dplyr)
library(tidyr)

Animals <- c("giraffes", "orangutans", "monkeys")
SF_Zoo <- c(20, 14, 23)
LA_Zoo <- c(12, 18, 29)
data <- data.frame(Animals, SF_Zoo, LA_Zoo) %>% 
  pivot_longer(cols = c(SF_Zoo, LA_Zoo)) %>% 
  mutate(Animals = paste(Animals, "<img src='https://images.plot.ly/language-icons/api-home/r-logo.png'</img>"))


plot_ly(data, x = ~Animals, y = ~value, type = 'bar', color = ~name) %>%
  layout(
    barmode = "stack"
  )

Image from code above

As can be seen the img tags get printed as literal string. I have tried wrapping tick labels Animals with htmltools::HTML but no joy.

This plotly guide talks about embedding images/logos within the plot area, but I would like to embed images as part of the tick labels. And this python SO solution replaces the tick labels with images entirely.


Solution

  • Just like in the python answer, you can paste the images into the layout iterating over the x-values of your data. For this you could use lapply to build the image-list. Use xref = "x" as described here. I would also create some space below the plot for the images using margin = list(b = 150), but you could also push them to a background layer using layer="below". You can then use xanchor = "center" to always center the images.

    out

    Code

    library(plotly)
    library(dplyr)
    library(tidyr)
    
    Animals <- c("giraffes", "orangutans", "monkeys")
    imgs <- c(
      "https://cdn.pixabay.com/photo/2017/04/11/21/34/giraffe-2222908_640.jpg",
      "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcRfPhPFLZSG51k0T3Mg0m8EWmek_sDLO9LsAh8kbVoOkzVHFKdAsbZmY4xfaIMVFq4uxcUKWV8LkS8D_nwK2AsTmA",
      "https://cdn.mos.cms.futurecdn.net/ZRAWdgHeNNPw8PaSxg7kVj-1200-80.jpg"
    )
    
    SF_Zoo <- c(20, 14, 23)
    LA_Zoo <- c(12, 18, 29)
    data <- data.frame(Animals, SF_Zoo, LA_Zoo) %>% 
      pivot_longer(cols = c(SF_Zoo, LA_Zoo))
    
    img_list <- lapply(seq_along(Animals), function(i, size = 0.4) {
      list(
        source = imgs[i],  
        xref = "x",       
        yref = "paper",   
        x = Animals[i],   
        y = -0.15,        
        sizex = size, sizey = size,
        xanchor = "center"
      )
    })
    
    plot_ly(data, x = ~Animals, y = ~value, type = 'bar', color = ~name) %>%
      layout(
        barmode = "stack",
        images = img_list,
        margin = list(b = 150) # adjust bottom margin
      )