Home > Mobile >  Plotly R : how to add dynamic annotation which belongs to frame
Plotly R : how to add dynamic annotation which belongs to frame

Time:05-10

I'm struggeling on a simple task. I have a database with 3 columns :

  • Year (numeric)
  • Age (numeric)
  • Pop (numeric)
  • Part60 : The % of individuals with age >= 60 (string like '% of poeple over 60 : 12%'). This value is the same for each rows of a year. Dataset looks like :

enter image description here

I built a plotly bargraph with a frame based on the year. So I have a slider which allow me to show for each age the number of individuals and this is animated year by year.

I would like to add an anotation which shows the value of Part60 for the year of the frame... I know that it's possible with a ggplot sent to ggplotly function, however I want to do it from scratch with a plot_ly function as parameters are (for me) easier to control and follow the logic of my code.

enter image description here

This is my code :

gH <- plot_ly(data = dataH,
              name = 'Hommes',
              marker = list(color = ispfPalette[4]),
              x = ~Pop,
              y = ~Age,
              frame = ~Annee)
gH <- gH %>% layout(yaxis = list(categoryorder="array",
                                 categoryarray=dataH$Age))
gH <- gH %>% layout(yaxis = list(title = '',
                                 zeroline = TRUE,
                                 showline = TRUE,
                                 showticklabels = TRUE,
                                 showgrid = FALSE), 
                    xaxis = list(title = '',
                                 zeroline = TRUE,
                                 showline = TRUE,
                                 autorange = "reversed"),
                    shapes = hline(60)) 
gH <- gH %>% add_annotations(
  x = 3000,
  y = 62,
  text = 'Part des 60 ans et   : 12 %',
  showarrow = F,
  color = ispfPalette[8]

Where text = 'Part des 60 ans et : 12 %' should be replaced by something which allow me to get the value which belongs to the year of the slider.

Is someone may help me to do it ?

Thanks in advance for your great help.

CodePudding user response:

Since I don't have your data, it's pretty difficult to give you the best answer. Although, here is a method in which you can add text that changes throughout the animation.

library(plotly)
library(tidyverse)

data(gapminder, package = "gapminder")
str(gapminder)

funModeling::df_status(gapminder)
# continent, lifeExp, year

gap <- gapminder %>% group_by(year, continent) %>%
  summarise(Expectancy = mean(lifeExp))

# plot 
p1 <- plot_ly(gap, x = ~Expectancy, y = ~continent,
              frame = ~year, type = 'bar', 
              showlegend = F,
              hovertemplate = paste0("Continent: %{y}<br>",
                                     "<extra></extra>"),
              texttemplate = "Life Expectancy: %{x:.2f}") %>%
  layout(yaxis=list(title=""), 
         xaxis=list(title="Average Life Expectancy per Continent By Year"),
         title=list(text=paste("Fancy Title")),
         margin = list(t = 100))
p1

enter image description here

If you had text you wanted to animate that is not connected to each marker (bar, point, line), then you could do it this way.

# Something to add in the annotation text
gap2 <- gap %>% filter(continent == "Asia") %>% 
  droplevels() %>% 
  arrange(year)

# build to see frames
p2 <- plotly_build(p1)

# modify frames; need an annotation for each frame
# make sure the data is in order by year (order by frame)
lapply(1:nrow(gap2), # for each frame
       function(i){
         annotation = list(
           data = gap2,
           type = "text",
           x = 77,
           y = .5,
           yref = "paper",
           showarrow = F,
           text = paste0("Asian Life Expectancy<br>", 
                         sprintf("%.2f", gap2[i, ]$Expectancy)), 
           font = list(color = "#b21e29", size = 16))
         p2$x$frames[[i]]$layout <<- list(annotations = list(annotation)) # change plot
       })
p2

enter image description here

If anything is unclear, let me know.

  • Related