Black Lives Matter. Please consider donating to Black Girls Code today.

How do I force identical colors for all plots in a subplot?

In the following example, I have four box plots within a subplot. Each of the four boxplots in this example has 3 variables: stocks, bonds and cash. In each of the box plots, I’d like stocks to show in the same color (e.g., blue), bonds to show in the same color (e.g., red), and cash to show as a third color. The code I have below causes me to have 12 colors, not 3. I’ve made a simple example. In my actual problem, the number of variables will be determined at runtime, so I can’t hard-code the colors easily. I’d like to make a call to a palette.

library(RColorBrewer)
library(plotly)
set.seed(101)
tbl1y <- data.frame(stocks = rnorm(1000,10,15),
                   bonds = rnorm(1000, 7, 8),
                   cash = rnorm(1000,3,1))
tbl3y <- data.frame(stocks = rnorm(1000,10,15*0.75),
                    bonds = rnorm(1000, 7, 8*0.75),
                    cash = rnorm(1000,3,1*0.75))
tbl5y <- data.frame(stocks = rnorm(1000,10,15*0.5),
                    bonds = rnorm(1000, 7, 8*0.5),
                    cash = rnorm(1000,3,1*0.5))
tbl10y <- data.frame(stocks = rnorm(1000,10,15*0.25),
                    bonds = rnorm(1000, 7, 8*0.25),
                    cash = rnorm(1000,3,1*0.25))

create_1boxplot <- function(tbl, n, vnames){
    mypalette <- brewer.pal(length(vnames), "Dark2")
    p <- plot_ly(data = tbl, type="box")
    for(i in vnames){
        p <- p %>% 
            add_trace(y = tbl[,i], name = i)
    }
    a<-list(text=paste("Boxplot of", n, "Year Returns"),
            xref = "paper",
            yref = "paper",
            yanchor = "bottom",
            xanchor = "center",
            color = vnames,
            colors = mypalette,
            align = "left",
            valign = "top",
            x = 0.5,
            y = 1,
            showarrow = FALSE)
    p <- p %>% layout(annotations=a)
    return(p)
}

vnames <- c("stocks", "bonds", "cash")
p1 <- create_1boxplot(tbl1y, 1, vnames = vnames)
p3 <- create_1boxplot(tbl3y, 3, vnames = vnames)
p5 <- create_1boxplot(tbl5y, 5, vnames = vnames)
p10 <- create_1boxplot(tbl10y, 10, vnames = vnames)

subplot(p1, p3, p5, p10, titleX=FALSE, titleY=FALSE, nrows=2, margin=0.05) %>%
    layout(showlegend = FALSE,
           yaxis = list(title = ""), 
           xaxis = list(title = ""))

Rplot

@rmacey, I did this using the colorway attribute in the layout of each of the subplots. Although, plot_ly(data = tbl, type="box") is also treated as a trace so I needed to make sure that length(mypallet) = length(vnames) + 1 otherwise things went out of sync.

library(RColorBrewer)
library(plotly)
set.seed(101)
tbl1y <- data.frame(stocks = rnorm(10,10,15),
                   bonds = rnorm(10, 7, 8),
                   cash = rnorm(10,3,1))
tbl3y <- data.frame(stocks = rnorm(10,10,15*0.75),
                    bonds = rnorm(10, 7, 8*0.75),
                    cash = rnorm(10,3,1*0.75))
tbl5y <- data.frame(stocks = rnorm(10,10,15*0.5),
                    bonds = rnorm(10, 7, 8*0.5),
                    cash = rnorm(10,3,1*0.5))
tbl10y <- data.frame(stocks = rnorm(10,10,15*0.25),
                    bonds = rnorm(10, 7, 8*0.25),
                    cash = rnorm(10,3,1*0.25))

create_1boxplot <- function(tbl, n, vnames){
    mypalette <- brewer.pal(length(vnames)+1, "Dark2")
    p <- plot_ly(data = tbl, type="box")
    for(i in vnames){
        p <- p %>% 
            add_trace(y = tbl[,i], name = i)
    }
    a<-list(text=paste("Boxplot of", n, "Year Returns"),
            xref = "paper",
            yref = "paper",
            yanchor = "bottom",
            xanchor = "center",
            color = vnames,
            colors = mypalette,
            align = "left",
            valign = "top",
            x = 0.5,
            y = 1,
            showarrow = FALSE)
    p <- p %>% layout(colorway=mypalette, annotations=a)
    return(p)
}

vnames <- list("stocks", "bonds", "cash")
p1 <- create_1boxplot(tbl1y, 1, vnames = vnames)
p3 <- create_1boxplot(tbl3y, 3, vnames = vnames)
p5 <- create_1boxplot(tbl5y, 5, vnames = vnames)
p10 <- create_1boxplot(tbl10y, 10, vnames = vnames)

subplot(subplot(p1), subplot(p3), p5, p10,titleX=FALSE, titleY=FALSE, nrows=2, margin=0.05) %>%
    layout(showlegend = FALSE,
           yaxis = list(title = ""), 
           xaxis = list(title = ""))
1 Like