Home > Mobile >  Add dynamic vertical line trace to plotly animated horizontal bar plot
Add dynamic vertical line trace to plotly animated horizontal bar plot

Time:05-03

I have a horizontal animated bar plot using the plotly package. I want to add a vertical line to show the median of the bar values and I want this to change value along with the frames of the bars.

Simplified example:

data <- data_frame(Year=c(1995, 1995, 1995, 1996, 1996, 1996, 1997, 1997, 1997, 1998, 1998, 1998),
                 Highest_Degree=c("Associate's", "Bachelor's", "PhD",
                                     "Associate's", "Bachelor's", "PhD",
                                     "Associate's", "Bachelor's", "PhD",
                                     "Associate's", "Bachelor's", "PhD"),
                 Salary=c(35200, 45270, 79670,
                             41950, 56330, 99410,
                             42780, 55930, 100000,
                             42860, 56080, 100000)
                 )

#plot 
plot_ly(data, x=~Salary, y=~Highest_Degree, frame=~Year, type = 'bar') %>%
layout(yaxis=list(title=" "), xaxis=list(title="Median Salary (USD)"),
       title=list(text=paste("Median Salary by Education Level 1995-1998")))

##to get medians list
medians <- data %>% 
select(c(Year, Salary)) %>%
group_by(Year) %>% 
summarise(Median=median(Salary))

Image example, except it needs to change with the rest of the animation: enter image description here

UPDATE: I added the overall medians to my original data frame and added a horizontal line with a trace (image below), but the line doesn't span the entire height of the plot. Is there a way to do this with 'shapes' in layout when the y axis is not numeric so that it spans the entire plot? enter image description here

CodePudding user response:

It might be easiest to start by building the plotly plot and manually modifying the frames' layouts. After that, I used vectorization to change the frames, so I wanted to ensure that the medians were in order by year. With such a small dataset, it's probably not necessary to do this by code, but I figured this is just a small snapshot of what you're working with.

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

# modify frames
# first, make sure the data is in order by year (order by frame)
medians <- arrange(medians, Year)

lapply(1:nrow(medians), # for each frame
       function(i){
         vline = list(
           type = "line",
           y0 = 0,
           y1 = 1,
           yref = "paper",
           x0 = unlist(medians[i, ]$Median), # median for that frame
           x1 = unlist(medians[i, ]$Median),
           line = list(color = "black", dash = "dot") # you can mod here!
           )
         p2$x$frames[[i]]$layout <<- list(shapes = list(vline)) # change plot
       })

After that, you can just call p2 to plot it.

enter image description here

  • Related