Plotly Error Bar Hack

Hack to fix error bar issue when using plotly
R
Shiny
Author

Harvey

Published

October 26, 2017

Plotly is a great plotting library that I’ve started to use extensively in part due to the ease in connecting graphs together under R. There is, however, a bug when using error bars in conjunction with a group variable - error bars are not drawn in the correct order. This can be fixed with a hack by adding each group as an individual trace.

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

## Raw data
df <- data.frame(sample = rep(paste0('sample ', 1:5), 4),
                 x = rnorm(20),
                 group = rep(paste0('group ', 1:2), each = 10),
                 stringsAsFactors = FALSE
)

## Stats table
df2 <- df %>%
  group_by(sample, group) %>%
  summarise(avg = mean(x), sd = sd(x)) %>%  ungroup()

df2
# A tibble: 10 × 4
   sample   group       avg     sd
   <chr>    <chr>     <dbl>  <dbl>
 1 sample 1 group 1  1.13   0.816 
 2 sample 1 group 2  0.946  1.55  
 3 sample 2 group 1  0.798  2.98  
 4 sample 2 group 2 -0.0644 1.11  
 5 sample 3 group 1  1.48   0.0388
 6 sample 3 group 2 -0.439  0.346 
 7 sample 4 group 1 -0.507  0.225 
 8 sample 4 group 2  1.59   0.779 
 9 sample 5 group 1  0.820  1.82  
10 sample 5 group 2  0.542  1.13  
## Plotly barchart with error bars.  Error bars are incorrectly assigned
p1 <- plot_ly(df2, x = ~sample, y = ~avg, color = ~group, type = 'bar', error_y = list(array = ~df2$sd))
p1
## Create individual columns for group data and errors
df3 <- df2 %>%
  gather(key, value, -c(sample, group)) %>%
  mutate(ref = paste0(group, ifelse(key == 'sd', '_sd', ''))) %>%
  select(-group, -key) %>%
  spread(ref, value)

df3
# A tibble: 5 × 5
  sample   `group 1` `group 1_sd` `group 2` `group 2_sd`
  <chr>        <dbl>        <dbl>     <dbl>        <dbl>
1 sample 1     1.13        0.816     0.946         1.55 
2 sample 2     0.798       2.98     -0.0644        1.11 
3 sample 3     1.48        0.0388   -0.439         0.346
4 sample 4    -0.507       0.225     1.59          0.779
5 sample 5     0.820       1.82      0.542         1.13 
## Plotly barchart displays error bars correctly
p2 <- plot_ly(df3, type = 'bar')
for (g in unique(df2$group)) {
  p2 <- add_trace(p2, x = df3[['sample']], y = df3[[g]], name = g, color = g, error_y = list(array = df3[[paste0(g, '_sd')]]))
}
p2