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