Discrete Colors in R
How to use and configure discrete color sequences, also known as categorical or qualitative color scales in R.
New to Plotly?
Plotly is a free and open-source graphing library for R. We recommend you read our Getting Started guide for the latest installation or upgrade instructions, then move on to our Plotly Fundamentals tutorials or dive straight in to some Basic Charts tutorials.
Discrete vs Continuous Color
In the same way as the X or Y position of a mark in cartesian coordinates can be used to represent continuous values (i.e. amounts or moments in time) or categories (i.e. labels), color can be used to represent continuous or discrete data. This page is about using color to represent categorical data using discrete colors, but Plotly can also represent continuous values with color.
Discrete Color Concepts
This document explains the following discrete-color-related concepts:
- color sequences are lists of colors to be mapped onto discrete data values. No interpolation occurs when using color sequences, unlike with continuous color scales, and each color is used as-is. Color sequence defaults depend on the
colors
attribute and can be explicitly specified using a vector of colors as argument. - legends are visible representations of the mapping between colors and data values. Legend markers also change shape when used with various kinds of traces, such as symbols or lines for scatter-like traces. Legends are configurable under the
layout.legend
attribute. Legends are the discrete equivalent of continuous color bars
Discrete Color with Plotly
Most Plotly functions accept a color
argument which automatically assigns data values to discrete colors if the data is non-numeric. If the data is numeric, the color will automatically be considered continuous. This means that numeric strings must be parsed to be used for continuous color, and conversely, numbers used as category codes must be converted to strings.
For example, in the tips
dataset, the smoker
column contains strings:
library(plotly)
library(reshape)
data("tips")
fig <- plot_ly(tips, x = ~total_bill, y = ~tip, split = ~smoker, type = 'scatter', mode = 'markers') %>%
layout(legend=list(title=list(text='smoker')), title = "String 'smoker' values mean discrete colors",
plot_bgcolor='#e5ecf6',
xaxis = list(
zerolinecolor = '#ffff',
zerolinewidth = 2,
gridcolor = 'ffff'),
yaxis = list(
zerolinecolor = '#ffff',
zerolinewidth = 2,
gridcolor = 'ffff') )
fig
The size
column, however, contains numbers:
library(plotly)
library(reshape)
data("tips")
fig <- plot_ly(tips, x = ~total_bill, y = ~tip, color = ~size, type = 'scatter', mode = 'markers') %>%
layout(title = "Numeric 'size' values mean continuous color",
plot_bgcolor='#e5ecf6',
xaxis = list(
zerolinecolor = '#ffff',
zerolinewidth = 2,
gridcolor = 'ffff'),
yaxis = list(
zerolinecolor = '#ffff',
zerolinewidth = 2,
gridcolor = 'ffff') )
fig
Converting this column to strings is very straightforward, but note that the ordering in the legend may not be sequential by default, but here it produces sequentially (see below for how to control discrete order):
library(plotly)
library(reshape)
data("tips")
tips$size = as.character(tips$size) #convert to string
fig <- plot_ly(tips, x = ~total_bill, y = ~tip, split = ~size, type = 'scatter', mode = 'markers') %>%
layout(title = "String 'size' values mean discrete colors",
plot_bgcolor='#e5ecf6',
xaxis = list(
zerolinecolor = '#ffff',
zerolinewidth = 2,
gridcolor = 'ffff'),
yaxis = list(
zerolinecolor = '#ffff',
zerolinewidth = 2,
gridcolor = 'ffff') )
fig
### Discrete Colors in Dash
[Dash for R](https://dashr.plotly.com/) is an open-source framework for building analytical applications, with no Javascript required, and it is tightly integrated with the Plotly graphing library.
Learn about how to install Dash for R at https://dashr.plot.ly/installation.
Everywhere in this page that you see fig, you can display the same figure in a Dash for R application by passing it to the figure argument.
``` r
library(dash)
library(dashCoreComponents)
library(dashHtmlComponents)
library(plotly)
app <- Dash$new()
app$layout(
htmlDiv(
list(
dccGraph(id = 'graph'),
htmlLabel("Color mode:"),
dccRadioItems(
id='radio',
options = list(list(label = "discrete", value = "d"),
list(label = "continuous", value = "c")),
value = 'Secondary'
)
)
)
)
app$callback(
output(id = 'graph', property='figure'),
params=list(input(id='radio', property='value')),
function(value) {
if(value == 'd'){
library(plotly)
library(reshape)
data("tips")
fig <- plot_ly(tips, x = ~total_bill, y = ~tip, split = ~size, type = 'scatter', mode = 'markers') %>%
layout(title = "'size' values mean discrete colors")
return(fig)
}
else{
library(plotly)
library(reshape)
data("tips")
fig <- plot_ly(tips, x = ~total_bill, y = ~tip, color = ~size, type = 'scatter', mode = 'markers') %>%
layout(title = "'size' values mean continuous color")
return(fig)
}
})
Use app$run_server()
to run the dash app.
Color Sequences in Plotly
By default, Plotly will use the color sequence from the colors
attribute, and the default active template is plotly
which uses the plotly
color sequence. You can choose any of the following built-in qualitative color sequences however, or define your own.
library("RColorBrewer")
display.brewer.all(type = 'qual')
Here is an example that creates a scatter plot using Plotly , with points colored using the built-in qualitative accent
color sequence.
library(plotly)
library(gapminder)
data("gapminder")
fig <- plot_ly(gapminder, x = ~year, y = ~lifeExp, type = 'scatter', mode = 'lines', color = ~continent,
line =list(colorscale = 'Accent')) %>%
layout(title = 'Built-in Accent color sequence', legend=list(title=list(text='continent')),
plot_bgcolor='#e5ecf6',
xaxis = list(
zerolinecolor = '#ffff',
zerolinewidth = 2,
gridcolor = 'ffff'),
yaxis = list(
zerolinecolor = '#ffff',
zerolinewidth = 2,
gridcolor = 'ffff') )
fig
Explicitly Constructing a Color Sequence
The Plotlycolors
argument accepts explicitly-constructed color sequences as well, as lists of CSS colors:
library(plotly)
library(gapminder)
data("gapminder")
data <- gapminder[gapminder$year == 2007, ]
fig <- plot_ly()%>%
add_bars(data = data, x = ~pop, y = ~continent, width = 1, color = ~continent, orientation = 'h', text = ~ country,
hovertemplate = paste('<b>%{text}</b>',
'<br><b>Continent</b>: %{y}<br>',
'<i>pop</i>: $%{x}'),
colors = c("red", "green", "blue", "goldenrod", "magenta")
) %>%
layout( title = "Explicit color sequence", legend=list(title=list(text='continent')),
plot_bgcolor='#e5ecf6',
xaxis = list(
zerolinecolor = '#ffff',
zerolinewidth = 2,
gridcolor = 'ffff'),
yaxis = list(
zerolinecolor = '#ffff',
zerolinewidth = 2,
gridcolor = 'ffff'))
fig
Warning: If your color sequence has fewer colors than the number of unique values in the column you are mapping to color
, the given colors will be mapped for some values and random colors will be mapped for other values :
library(plotly)
data("tips")
fig <- plot_ly(tips, x = ~total_bill, y = ~tip, type = 'scatter', mode = 'markers', color = ~day,
colors = c("red", "blue"))
fig <- fig %>%
layout( title = "Ambiguous! given colors mapped to some values only", legend=list(title=list(text='day')),
plot_bgcolor='#e5ecf6',
xaxis = list(
zerolinecolor = '#ffff',
zerolinewidth = 2,
gridcolor = 'ffff'),
yaxis = list(
zerolinecolor = '#ffff',
zerolinewidth = 2,
gridcolor = 'ffff'))
fig
Directly Mapping Colors to Data Values
The example above assigned colors to data values on a first-come-first-served basis, but you can directly map colors to data values if this is important to your application with colors
. Note that this does not change the order in which values appear in the figure or legend, as can be controlled below:
library(plotly)
library(gapminder)
data("gapminder")
pal <- c("red", "green", "blue", "goldenrod", "magenta")
pal <- setNames(pal, c("Europe", "Asia", "Americas", "Oceania", "Africa"))
fig <- plot_ly()%>%
add_bars(data = data, x = ~pop, y = ~continent, width = 1, color = ~continent, orientation = 'h',
text = ~ country,
hovertemplate = paste('<b>%{text}</b>',
'<br><b>Continent</b>: %{y}<br>',
'<i>pop</i>: $%{x}'),
colors = pal) %>%
layout( title = "Explicit color mapping", legend=list(title=list(text='continent')),
plot_bgcolor='#e5ecf6',
xaxis = list(
zerolinecolor = '#ffff',
zerolinewidth = 2,
gridcolor = 'ffff'),
yaxis = list(
zerolinecolor = '#ffff',
zerolinewidth = 2,
gridcolor = 'ffff'))
fig
If your data set already contains valid CSS colors which you wish to use directly, you can pass the special value "identity"
to colors
, in which case the legend is hidden by default, and the color does not appear in the hover label:
library(plotly)
library(gapminder)
data(gapminder)
fig <- plot_ly(x = c("a","b","c"), y = c(1,3,2), type = 'bar',
marker = list(color = c('red', 'goldenrod',
'#00D')))
fig <- fig %>% layout(plot_bgcolor='#e5ecf6',
xaxis = list(
title = 'x',
zerolinecolor = '#ffff',
zerolinewidth = 2,
gridcolor = 'ffff'),
yaxis = list(
title = 'y',
zerolinecolor = '#ffff',
zerolinewidth = 2,
gridcolor = 'ffff'
))
fig
Controlling Discrete Color Order
Plotly lets you specify an ordering over categorical variables with categoryorder
, which will apply to colors and legends as well as symbols and axes. This can be used with either colors
or color
.
library(plotly)
library(gapminder)
data("gapminder")
data <- gapminder[gapminder$year == 2007, ]
pal <- c("green", "blue", "magenta", "red", "goldenrod")
pal <- setNames(pal, c("Europe", "Asia", "Americas", "Oceania", "Africa"))
fig <- plot_ly()%>%
add_bars(data = data, x = ~pop, y = ~continent, width = 1, color = ~continent, orientation = 'h',
text = ~ country,
hovertemplate = paste('<b>%{text}</b>',
'<br><b>Continent</b>: %{y}<br>',
'<i>pop</i>: $%{x}'),
colors = pal) %>%
layout( title = "Explicit color sequence with explicit ordering", legend=list(title=list(text='continent')),
plot_bgcolor='#e5ecf6',
xaxis = list(
zerolinecolor = '#ffff',
zerolinewidth = 2,
gridcolor = 'ffff'),
yaxis = list(
categoryorder = "array",
categoryarray = c("Asia","Oceania", "Europe", "Africa", "Americas"),
zerolinecolor = '#ffff',
zerolinewidth = 2,
gridcolor = 'ffff'),
bargap = 1)
fig
library(plotly)
library(gapminder)
data("gapminder")
data <- gapminder[gapminder$year == 2007, ]
pal <- c("red", "green", "blue", "goldenrod", "magenta")
pal <- setNames(pal, c("Europe", "Asia", "Americas", "Oceania", "Africa"))
fig <- plot_ly()%>%
add_bars(data = data, x = ~pop, y = ~continent, width = 1, color = ~continent, orientation = 'h',
text = ~ country,
hovertemplate = paste('<b>%{text}</b>',
'<br><b>Continent</b>: %{y}<br>',
'<i>pop</i>: $%{x}'),
colors = pal) %>%
layout( title = "Explicit color mapping with explicit ordering", legend=list(title=list(text='continent')),
plot_bgcolor='#e5ecf6',
xaxis = list(
zerolinecolor = '#ffff',
zerolinewidth = 2,
gridcolor = 'ffff'),
yaxis = list(
categoryorder = "array",
categoryarray = c("Asia","Oceania", "Europe", "Africa", "Americas"),
zerolinecolor = '#ffff',
zerolinewidth = 2,
gridcolor = 'ffff'),
bargap = 1)
fig
What About Dash?
Dash for R is an open-source framework for building analytical applications, with no Javascript required, and it is tightly integrated with the Plotly graphing library.
Learn about how to install Dash for R at https://dashr.plot.ly/installation.
Everywhere in this page that you see fig
, you can display the same figure in a Dash for R application by passing it to the figure
argument of the Graph
component from the built-in dashCoreComponents
package like this:
library(plotly)
fig <- plot_ly()
# fig <- fig %>% add_trace( ... )
# fig <- fig %>% layout( ... )
library(dash)
library(dashCoreComponents)
library(dashHtmlComponents)
app <- Dash$new()
app$layout(
htmlDiv(
list(
dccGraph(figure=fig)
)
)
)
app$run_server(debug=TRUE, dev_tools_hot_reload=FALSE)