Jimbou Jimbou - 2 months ago 48
R Question

Plotly Bar chart, add a second factor for coloring, opacity or border color

I want to render a

plotly
bar chart in a shiny application adding two factors.
One factor is no problem, the second makes trouble. And I'm not sure if its possible at all.

Here is some data.
C
is the grouping factor for grouping or coloring. This is relatively easy and straightforward.

set.seed(123)
df <- data.frame(A=letters[1:5],B=runif(5),C=sample(1:3,5,replace = T))
df <- df[order(df$B, decreasing = T),]
df
A B C
5 e 0.9404673 2
4 d 0.8830174 2
2 b 0.7883051 2
3 c 0.4089769 3
1 a 0.2875775 1

library(plotly)
plot_ly(df, type = "bar", x = A, y = B, group = C)


enter image description here

Now I'm trying to add a further variable to change the border (e.g. in red, but could be that this isn't possible) or the opacity. Important is, that I don't want to change the legend or overall grouping. Only add a red line or add opacity to some bars.

So, I add some data:

df$D <- c(0.2, 1, 0.2, 1, 0.2)


But everthing I tried is not working.

plot_ly(df, type = "bar", x = A, y = B, color = as.factor(C)) # similar, but different order
plot_ly(df, type = "bar", x = A, y = B, group = as.factor(C)) # same order, other colors
plot_ly(df, type = "bar", x = A, y = B, group = C, color = as.factor(C)) #adds a second group
plot_ly(df, type = "bar", x = A, y = B, group = C, opacity = as.factor(D)) # no idea whats happening
plot_ly(df, type = "bar", x = A, y = B, color = as.factor(C), opacity = as.factor(D)) # the opacity of e is wrong


Do you have an idea to solve the problem using perhaps
interaction()
and
plotly::add_trace()
together or something else?

My expected output, bars with
D==0.2
are shown with a more thicker border:
enter image description here

Answer

You could try:

df %>% 
  plot_ly(x = A, y = B, type = "bar", group = C, 
          marker = list(line = list(width = ifelse(D == 0.2, 10, NA), 
                                    color = ifelse(D == 0.2, "red", NA))),
          showlegend = FALSE)

Which gives:

enter image description here


Update:

Should you want to control opacity instead, I guess you could play with toRGB():

cols <- RColorBrewer::brewer.pal(length(unique(df$C)), name = "Set1")
df$color <- factor(df$C, labels = cols)

df %>% 
  plot_ly(x = A, y = B, type = "bar",
          marker = list(color = toRGB(color, alpha = D)))

enter image description here

Although the legend is still going to be a problem using this approach.

Comments