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.38  0.733
 2 sample 1 group 2  1.23  0.344
 3 sample 2 group 1 -1.04  0.649
 4 sample 2 group 2  0.162 0.387
 5 sample 3 group 1 -0.142 2.08 
 6 sample 3 group 2  0.272 0.284
 7 sample 4 group 1  0.769 1.54 
 8 sample 4 group 2 -0.238 0.100
 9 sample 5 group 1  0.715 0.568
10 sample 5 group 2  0.340 0.378
## 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.38         0.733     1.23         0.344
2 sample 2    -1.04         0.649     0.162        0.387
3 sample 3    -0.142        2.08      0.272        0.284
4 sample 4     0.769        1.54     -0.238        0.100
5 sample 5     0.715        0.568     0.340        0.378
## 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