简体   繁体   中英

Plotly: How to customize colors in a stacked bar chart?

I would like to ask you if you could help me in customizing of colors in a stacked bar chart created by plotly.

The problem is following - I have to recreate a dashboard (from an excel file to a html file). A part of the dashboard is a chart providing us with information about early production of each entity. The chart is a stacked bar chart type by plotly. As each entity is defined by a specific color (defined in RGB) throughout whole dashboard, I need to keep these colors in the donut chart as well. But there is a problem. I always get the following warning:

Warning message: In RColorBrewer::brewer.pal(N, "Set2"): n too large, allowed maximum for palette Set2 is 8 Returning the palette you asked for with that many colors

and the resulting donut chart containts only one Entity with a not-specified color. Also, the colors in the legend are not those which are defined.

Any idea what to do with it? Thank you so much in advance.

Code:

library(dplyr)
library(plotly)

dt <- as.data.frame(matrix(ncol = 13, nrow = 19))
colnames(dt) <- c("Entity", month.abb)

for (i in 1:nrow(dt)) {
  dt[i, 1] <- paste("Entity", i, sep="")
  dt[i, -1] <- floor(runif(12, min=0, max=100))
}

# assign colors to entities

dt$"EntityColor" <- c("#074263", "#0B5394", "#3D85C6", "#6D9EEB", "#A4C2F4", "#CFE2F3", "#5B0F00", "#85200C", "#A61C00", "#CC4125", "#DD7E6B", "#E6B8AF", "#F8CBAD", "#F4CCCC", "#274E13", "#38761D", "#E06666", "#CC0000", "#20124D")

data.table::melt(dt) %>%

  plot_ly(x = ~variable,
          y = ~value,
          type = "bar",
          color = ~Entity,
          marker = list(colors = ~EntityColor)
  ) %>%

  layout(yaxis = list(title = ""),
         xaxis = list(title = ""),
         barmode = 'stack')

Plot:

在此处输入图像描述

Refined approach after comments:

Since the colors turned out to be a bit tricky (see initial suggestion below) I had to break the whole thing down and use a combination of plot_ly() and add_traces() in a loop to make sure that the plotly settings did not apply colors in the wrong order. The following plot should be exactly what you're looking for.

Plot:

在此处输入图像描述

Note that I've appended a continuous numerical column ID . Why? Because you wanted the names in alphabetical order, and the rows are added to the plot in the order they appear in your source. And It's a bit tricky since a straight up ordering using dt %>% arrange((Entity)) would give you Entity1, Enitity10, Entity11 etc. Let me know if you'd like to adjust this in any other way.

Code:

library(dplyr)
library(plotly)

# data
set.seed(123)

dt <- as.data.frame(matrix(ncol = 13, nrow = 19))
colnames(dt) <- c("Entity", month.abb)
for (i in 1:nrow(dt)) {
  dt[i, 1] <- paste("Entity", i, sep="")
  dt[i, -1] <- floor(runif(12, min=0, max=100))
}

# assign colors to entities
dt$"EntityColor" <- c("#074263", "#0B5394", "#3D85C6", "#6D9EEB", "#A4C2F4", "#CFE2F3", "#5B0F00", "#85200C", "#A61C00", "#CC4125", "#DD7E6B", "#E6B8AF", "#F8CBAD", "#F4CCCC", "#274E13", "#38761D", "#E06666", "#CC0000", "#20124D")



# sort data
dt$ID <- seq.int(nrow(dt))
dt <- dt %>% arrange(desc(ID))


# specify month as factor variable to ensure correct order
months=names(dt)[2:13]
months<- factor(months, levels = c(months))

# plotly setup
p <- plot_ly(type = 'bar')

# add trace for each entity
nrows = nrow(dt)
for(i in 1:nrows) {
    p <- p %>% add_trace(x=months, y = unlist(dt[i,2:13], use.names=F), type = 'bar',
                         #name = paste(dt[i,1], dt[i,14], sep = "_"),
                         name = dt[i,1],
                         type = 'bar',  
                         marker=list(color = dt[i,14])) %>%
       layout(barmode = 'stack')

}

# Edit layout
p <- p %>% layout(title = list(xanchor='right', text='Correct colors, orderered legend'),
                  yaxis = list(title = ''),
                  xaxis = list(title = 'month'))
p

Color correctness verification:

在此处输入图像描述

Initial suggestion

Here's an initial suggestion. First of all, color = ~Entity has got to go. And marker = list(color = ~EntityColor) versus marker = list(colors = ~EntityColor) gives two different results. What makes matters even stranger is that the pie chart documentation uses:

marker = list(colors = colors, ...)

... and the bar chart documentation uses:

marker = list(color = c('rgba(204,204,204,1)', 'rgba(222,45,38,0.8)', ...)

...without the s at the end of color .

Either way, you should test both marker = list(color = ~EntityColor) and marker = list(colors = ~EntityColor) and see what's correct for you.

Plot:

在此处输入图像描述

Code:

dt <- as.data.frame(matrix(ncol = 13, nrow = 19))
colnames(dt) <- c("Entity", month.abb)

for (i in 1:nrow(dt)) {
  dt[i, 1] <- paste("Entity", i, sep="")
  dt[i, -1] <- floor(runif(12, min=0, max=100))
}

# assign colors to entities

dt$"EntityColor" <- c("#074263", "#0B5394", "#3D85C6", "#6D9EEB", "#A4C2F4", "#CFE2F3", "#5B0F00", "#85200C", "#A61C00", "#CC4125", "#DD7E6B", "#E6B8AF", "#F8CBAD", "#F4CCCC", "#274E13", "#38761D", "#E06666", "#CC0000", "#20124D")

data.table::melt(dt) %>%

  plot_ly(x = ~variable,
          y = ~value,
          name= ~Entity,
          type = "bar",
          #color = ~Entity,
          marker = list(colors = ~EntityColor)
  ) %>%

  layout(yaxis = list(title = ""),
         xaxis = list(title = ""),
         barmode = 'stack')

Take a look and see how it works out for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM