2

Here is a toy example I have got stuck on

library(plotly)
library(dplyr)

# construct data.frame
df <- tibble(x=c(3,2,3,5,5,5,2),y=c("a","a","a","b","b","b","b"))

# construct data.frame of last y values
  latest <- df %>% 
   group_by(y) %>% 
   slice(n())

# plot for one value of y (NB not sure why value for 3 appears?)
  p <- plot_ly() %>% 
   add_histogram(data=subset(df,y=="b"),x= ~x) %>%   
  add_histogram(data=subset(latest,y=="b"),x= ~x,marker=list(color="red")) %>%
  layout(barmode="overlay",showlegend=FALSE,title= ~y)
  p

enter image description here

How can i set these up as subplots, one for each unique value of y? In the real world example, I would have 20 different y's so would ideally loop or apply the code. In addition, it would be good to set standard x scales of say c(1:10) and have, for example, 2 rows

TIA

pssguy
  • 3,455
  • 7
  • 38
  • 68

1 Answers1

1
  1. build a list containing each of the plots
  2. set the bin sizes manually for the histograms, otherwise the automatic selection will choose different bins for each of the traces within a plot (making it look strange as in you example where the bars of each trace are different widths)
  3. use subplot to put it all together
  4. add titles to individual subplots using a list of annotations, as explained here

Like this:

N = nlevels(factor(df$y))
plot_list = vector("list", N)
lab_list = vector("list", N)

for (i in 1:N) {
  this_y = levels(factor(df$y))[i]
  p <- plot_ly() %>% 
    add_trace(type="histogram", data=subset(df,y==this_y), x=x, marker=list(color="blue"),
              autobinx=F, xbins=list(start=0.5, end=6.5, size=1)) %>%   
    add_trace(type="histogram", data=subset(latest,y==this_y), x = x, marker=list(color="red"), 
              autobinx=F, xbins=list(start=0.5, end=6.5, size=1)) %>%
    layout(barmode="overlay", showlegend=FALSE)
  plot_list[[i]] = p

  titlex = 0.5
  titley = c(1.05, 0.45)[i]
  lab_list[[i]] = list(x=titlex, y=titley, text=this_y, 
                       showarrow=F, xref='paper', yref='paper', font=list(size=18))
}

subplot(plot_list, nrows = 2) %>%
  layout(annotations = lab_list)

enter image description here

Community
  • 1
  • 1
dww
  • 30,425
  • 5
  • 68
  • 111
  • Thanks. I am getting close to what I need now. The issue is labeling each individual plot. With title=this_y, only the last value i.e. b gets shown at top(I think it is truncated out in your image). There is not a title shown for each subplot If i add shareX=TRUE to the subplot function I get the correct this_y showing up along the x axis BUT only for the botttom row. In the toy example it would just show b (nothing on the top subplot) . In my real life example, with 4 columns all of the bottom row have the correct this_y showing – pssguy Sep 01 '16 at 23:34
  • thanks. I get the general gist but am happy to wait on your answer in a few days time – pssguy Sep 02 '16 at 20:20
  • I've added in the titles using annotations – dww Sep 04 '16 at 18:10
  • Thanks will check it later. Sorry had not realized i had to click bounty button . Well merited – pssguy Sep 04 '16 at 22:06
  • I tried this solution, and I am getting :Error in add_trace(., type = "histogram", data = subset(df, y == this_y), : object 'x' not found > > subplot(plot_list, nrows = 2) %>% + layout(annotations = lab_list) Error in names(object) <- nm : attempt to set an attribute on NULL – Rene Chan Dec 02 '19 at 02:25
  • @Etienne - could be a couple of things. Either something about your data that is different. Or note that this answer is a few years old for version 3 of plotly. The newer version of Plotly has a bit different syntax, so that may be the reason. Suggest you post your data and what you tried already as a new question, otherwise hard to diagnose just from your comment. – dww Dec 02 '19 at 06:02