Skip to content

Introduce new Tableau colors #12009

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions doc/users/next_whats_new/introduce-new-tableau-colors.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
:orphan:

Introduce new Tableau colors
----------------------------

In its version 10, Tableau `introduced a new palette of categorical colors
<https://www.tableau.com/about/blog/2016/7/colors-upgrade-tableau-10-56782>`__.
Those are now available in matplotlib with the prefix ``tabx:``:
``{'tabx:blue', 'tabx:orange', 'tabx:red', 'tabx:cyan', 'tabx:green',
'tabx:yellow', 'tabx:purple', 'tabx:pink', 'tabx:brown', 'tabx:grey'}``

Those colors are also provided as a new ``tabx10`` colormap. An additional
``tabx20`` colormap with is added.

In general those colors are a little less saturated than those from the default
color cycle. Replacing the default color cycler with those colors can e.g. be
achieved via

::

cols = plt.cm.tabx10.colors
plt.rcParams["axes.prop_cycle"] = plt.cycler("color", cols)}


31 changes: 21 additions & 10 deletions examples/color/color_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Color Demo
==========

Matplotlib gives you 8 ways to specify colors,
Matplotlib gives you 7 ways to specify colors,

1) an RGB or RGBA tuple of float values in ``[0, 1]`` (e.g. ``(0.1, 0.2, 0.5)``
or ``(0.1, 0.2, 0.5, 0.3)``). RGBA is short for Red, Green, Blue, Alpha;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’d say tab10:

Are these all really different “ways” to specify colours? If we are to have all these palettes I suggest specifying a palette is another way and then list all the palettes as a sub list.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and then list all the palettes as a sub list

Yes that is a very good idea.

Expand All @@ -13,16 +13,25 @@
4) a single letter string, i.e. one of
``{'b', 'g', 'r', 'c', 'm', 'y', 'k', 'w'}``;
5) a X11/CSS4 ("html") color name, e.g. ``"blue"``;
6) a name from the `xkcd color survey <https://xkcd.com/color/rgb/>`__,
prefixed with ``'xkcd:'`` (e.g., ``'xkcd:sky blue'``);
6) a color name from a palette, prefixed with the palette's name:

a. a name from the `xkcd color survey <https://xkcd.com/color/rgb/>`__;
prefixed with ``'xkcd:'`` (e.g., ``'xkcd:sky blue'``);
b. one of ``{'tab:blue', 'tab:orange', 'tab:green',
'tab:red', 'tab:purple', 'tab:brown', 'tab:pink',
'tab:gray', 'tab:olive', 'tab:cyan'}`` which are the Tableau Colors from
the 'T10' categorical palette (which is the default color cycle);
c. one of ``{'tabx:blue', 'tabx:orange', 'tabx:red', 'tabx:cyan',
'tabx:green', 'tabx:yellow', 'tabx:purple', 'tabx:pink', 'tabx:brown',
'tabx:gray' }`` which are the colors from the
`new Tableau10 categorical palette
<https://www.tableau.com/about/blog/2016/7/colors-upgrade-tableau-10-\
56782>`__;

7) a "Cn" color spec, i.e. `'C'` followed by a single digit, which is an index
into the default property cycle
(``matplotlib.rcParams['axes.prop_cycle']``); the indexing occurs at artist
creation time and defaults to black if the cycle does not include color.
8) one of ``{'tab:blue', 'tab:orange', 'tab:green',
'tab:red', 'tab:purple', 'tab:brown', 'tab:pink',
'tab:gray', 'tab:olive', 'tab:cyan'}`` which are the Tableau Colors from the
'tab10' categorical palette (which is the default color cycle);

For more information on colors in matplotlib see

Expand All @@ -47,12 +56,14 @@
ax.set_xlabel('time (s)', color='c')
# 5) a named color:
ax.set_ylabel('voltage (mV)', color='peachpuff')
# 6) a named xkcd color:
# 6a) a named xkcd color:
ax.plot(t, s, 'xkcd:crimson')
# 6b) tab notation:
ax.tick_params(axis="x", labelcolor='tab:orange')
# 6c) tabx notation:
ax.tick_params(axis="y", labelcolor='tabx:yellow')
# 7) Cn notation:
ax.plot(t, .7*s, color='C4', linestyle='--')
# 8) tab notation:
ax.tick_params(labelcolor='tab:orange')


plt.show()
Expand Down
2 changes: 1 addition & 1 deletion examples/color/colormap_reference.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
('Qualitative', [
'Pastel1', 'Pastel2', 'Paired', 'Accent',
'Dark2', 'Set1', 'Set2', 'Set3',
'tab10', 'tab20', 'tab20b', 'tab20c']),
'tab10', 'tab20', 'tab20b', 'tab20c', 'tabx10', 'tabx20']),
('Miscellaneous', [
'flag', 'prism', 'ocean', 'gist_earth', 'terrain', 'gist_stern',
'gnuplot', 'gnuplot2', 'CMRmap', 'cubehelix', 'brg',
Expand Down
106 changes: 62 additions & 44 deletions examples/color/named_colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,52 +12,70 @@
* the :doc:`/gallery/color/color_demo`.
"""

import matplotlib.pyplot as plt
from matplotlib import colors as mcolors


colors = dict(mcolors.BASE_COLORS, **mcolors.CSS4_COLORS)

# Sort colors by hue, saturation, value and name.
by_hsv = sorted((tuple(mcolors.rgb_to_hsv(mcolors.to_rgba(color)[:3])), name)
for name, color in colors.items())
sorted_names = [name for hsv, name in by_hsv]

n = len(sorted_names)
ncols = 4
nrows = n // ncols

fig, ax = plt.subplots(figsize=(9, 8))

# Get height and width
X, Y = fig.get_dpi() * fig.get_size_inches()
h = Y / (nrows + 1)
w = X / ncols

for i, name in enumerate(sorted_names):
row = i % nrows
col = i // nrows
y = Y - (row * h) - h

xi_line = w * (col + 0.05)
xf_line = w * (col + 0.25)
xi_text = w * (col + 0.3)

ax.text(xi_text, y, name, fontsize=(h * 0.5),
horizontalalignment='left',
verticalalignment='center')

ax.hlines(y + h * 0.1, xi_line, xf_line,
color=colors[name], linewidth=(h * 0.6))

ax.set_xlim(0, X)
ax.set_ylim(0, Y)
ax.set_axis_off()
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors


def plot_colortable(colors, title, sort_colors=True, emptycols=0):

cell_width = 185
cell_height = 24
swatch_width = 38
margin = 10
topmargin = 30

# Sort colors by hue, saturation, value and name.
by_hsv = ((tuple(mcolors.rgb_to_hsv(mcolors.to_rgba(color)[:3])), name)
for name, color in colors.items())
if sort_colors is True:
by_hsv = sorted(by_hsv)
names = [name for hsv, name in by_hsv]

n = len(names)
ncols = 4 - emptycols
nrows = n // ncols + int(n % ncols > 0)

width = cell_width * 4 + 2 * margin
height = cell_height * nrows + margin + topmargin
dpi = 72

fig, ax = plt.subplots(figsize=(width / dpi, height / dpi), dpi=dpi)
fig.subplots_adjust(margin/width, margin/height,
(width-margin)/width, (height-topmargin)/height)
ax.set_xlim(0, cell_width * 4)
ax.set_ylim(cell_height * (nrows-0.5), -cell_height/2.)
ax.yaxis.set_visible(False)
ax.xaxis.set_visible(False)
ax.set_axis_off()
ax.set_title(title, fontsize=20, loc="left")

for i, name in enumerate(names):
row = i % nrows
col = i // nrows
y = row * cell_height

swatch_start_x = cell_width * col
swatch_end_x = cell_width * col + swatch_width
text_pos_x = cell_width * col + swatch_width + 5

ax.text(text_pos_x, y, name, fontsize=12,
horizontalalignment='left',
verticalalignment='center')

ax.hlines(y, swatch_start_x, swatch_end_x,
color=colors[name], linewidth=18)
plt.show()

plot_colortable(mcolors.BASE_COLORS, "Base Colors",
sort_colors=False, emptycols=1)
plot_colortable(mcolors.TABLEAU_COLORS, "Tableau Palette",
sort_colors=False, emptycols=1)
plot_colortable(mcolors.TABLEAUX_COLORS, "New Tableau Palette",
sort_colors=False, emptycols=1)
#sphinx_gallery_thumbnail_number = 4
plot_colortable(mcolors.CSS4_COLORS, "CSS Colors")

fig.subplots_adjust(left=0, right=1,
top=1, bottom=0,
hspace=0, wspace=0)
plt.show()

#############################################################################
#
Expand Down
49 changes: 49 additions & 0 deletions lib/matplotlib/_cm.py
Original file line number Diff line number Diff line change
Expand Up @@ -1346,6 +1346,53 @@ def _gist_yarg(x): return 1 - x
)


_tabx10colors = [
"#4e79a7", # blue
"#f28e2b", # orange
"#e15759", # red
"#76b7b2", # cyan
"#59a14f", # green
"#edc948", # yellow
"#b07aa1", # purple
"#ff9da7", # pink
"#9c755f", # brown
"#bab0ac", # grey
]

_tabx20colors = [
"#4e79a7", # blue
"#a0cbe8",
"#f28e2b", # orange
"#ffbe7d",
"#59a14f", # green
"#8cd17d",
"#b6992d", # yellow # is different from tabx10
"#f1ce63",
"#499894", # cyan # is different from tabx10
"#86bcb6",
"#e15759", # red
"#ff9d9a",
"#79706e", # grey # is different from tabx10
"#bab0ac",
"#d37295", # pink # is different from tabx10
"#fabfd2",
"#b07aa1", # purple # is different from tabx10
"#d4a6c8",
"#9d7660", # brown # is different from tabx10
"#d7b5a6",
]

_tabx10_data = []
for c in _tabx10colors:
d = [int(s, 16)/255. for s in list(map(''.join, zip(*[iter(c[1:])]*2)))]
_tabx10_data.append(d)

_tabx20_data = []
for c in _tabx20colors:
d = [int(s, 16)/255. for s in list(map(''.join, zip(*[iter(c[1:])]*2)))]
_tabx20_data.append(d)


datad = {
'Blues': _Blues_data,
'BrBG': _BrBG_data,
Expand Down Expand Up @@ -1423,4 +1470,6 @@ def _gist_yarg(x): return 1 - x
'tab20': {'listed': _tab20_data},
'tab20b': {'listed': _tab20b_data},
'tab20c': {'listed': _tab20c_data},
'tabx10': {'listed': _tabx10_data},
'tabx20': {'listed': _tabx20_data},
}
17 changes: 17 additions & 0 deletions lib/matplotlib/_color_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,23 @@
TABLEAU_COLORS = OrderedDict(
('tab:' + name, value) for name, value in TABLEAU_COLORS)

# These colors are from Tableau Version 10
TABLEAUX_COLORS = (
("blue", "#4e79a7"),
("orange", "#f28e2b"),
("red", "#e15759"),
("cyan", "#76b7b2"),
("green", "#59a14f"),
("yellow", "#edc948"),
("purple", "#b07aa1"),
("pink", "#ff9da7"),
("brown", "#9c755f"),
("gray", "#bab0ac")
)
# Normalize name to "tabx:<name>" to avoid name collisions.
TABLEAUX_COLORS = OrderedDict(
('tabx:' + name, value) for name, value in TABLEAUX_COLORS)

# This mapping of color names -> hex values is taken from
# a survey run by Randel Monroe see:
# http://blog.xkcd.com/2010/05/03/color-survey-results/
Expand Down
28 changes: 21 additions & 7 deletions lib/matplotlib/colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,21 @@
level (e.g., ``'0.5'``);
* one of ``{'b', 'g', 'r', 'c', 'm', 'y', 'k', 'w'}``;
* a X11/CSS4 color name;
* a name from the `xkcd color survey <https://xkcd.com/color/rgb/>`__;
prefixed with ``'xkcd:'`` (e.g., ``'xkcd:sky blue'``);
* one of ``{'tab:blue', 'tab:orange', 'tab:green',
'tab:red', 'tab:purple', 'tab:brown', 'tab:pink',
'tab:gray', 'tab:olive', 'tab:cyan'}`` which are the Tableau Colors from the
'T10' categorical palette (which is the default color cycle);
* a color name from a palette, prefixed with the palette's name:

* a name from the `xkcd color survey <https://xkcd.com/color/rgb/>`__;
prefixed with ``'xkcd:'`` (e.g., ``'xkcd:sky blue'``);
* one of ``{'tab:blue', 'tab:orange', 'tab:green',
'tab:red', 'tab:purple', 'tab:brown', 'tab:pink',
'tab:gray', 'tab:olive', 'tab:cyan'}`` which are the Tableau Colors from
the 'T10' categorical palette (which is the default color cycle);
* one of ``{'tabx:blue', 'tabx:orange', 'tabx:red', 'tabx:cyan',
'tabx:green', 'tabx:yellow', 'tabx:purple', 'tabx:pink', 'tabx:brown',
'tabx:gray' }`` which are the colors from the
`new Tableau10 categorical palette
<https://www.tableau.com/about/blog/2016/7/colors-upgrade-tableau-10-\
56782>`__;

* a "CN" color spec, i.e. `'C'` followed by a single digit, which is an index
into the default property cycle (``matplotlib.rcParams['axes.prop_cycle']``);
the indexing occurs at artist creation time and defaults to black if the
Expand All @@ -61,7 +70,8 @@

import numpy as np
import matplotlib.cbook as cbook
from ._color_data import BASE_COLORS, TABLEAU_COLORS, CSS4_COLORS, XKCD_COLORS
from ._color_data import (BASE_COLORS, TABLEAU_COLORS, TABLEAUX_COLORS,
CSS4_COLORS, XKCD_COLORS)


class _ColorMapping(dict):
Expand Down Expand Up @@ -89,6 +99,10 @@ def __delitem__(self, key):
_colors_full_map.update({k.replace('gray', 'grey'): v
for k, v in TABLEAU_COLORS.items()
if 'gray' in k})
_colors_full_map.update(TABLEAUX_COLORS)
_colors_full_map.update({k.replace('gray', 'grey'): v
for k, v in TABLEAUX_COLORS.items()
if 'gray' in k})
_colors_full_map.update(BASE_COLORS)
_colors_full_map = _ColorMapping(_colors_full_map)

Expand Down
3 changes: 2 additions & 1 deletion tutorials/colors/colormaps.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@

cmaps['Qualitative'] = ['Pastel1', 'Pastel2', 'Paired', 'Accent',
'Dark2', 'Set1', 'Set2', 'Set3',
'tab10', 'tab20', 'tab20b', 'tab20c']
'tab10', 'tab20', 'tab20b', 'tab20c',
'tabx10', 'tabx20']

###############################################################################
# Miscellaneous
Expand Down
21 changes: 15 additions & 6 deletions tutorials/colors/colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,21 @@
level (e.g., ``'0.5'``);
* one of ``{'b', 'g', 'r', 'c', 'm', 'y', 'k', 'w'}``;
* a X11/CSS4 color name;
* a name from the `xkcd color survey <https://xkcd.com/color/rgb/>`__;
prefixed with ``'xkcd:'`` (e.g., ``'xkcd:sky blue'``);
* one of ``{'tab:blue', 'tab:orange', 'tab:green',
'tab:red', 'tab:purple', 'tab:brown', 'tab:pink',
'tab:gray', 'tab:olive', 'tab:cyan'}`` which are the Tableau Colors from the
'T10' categorical palette (which is the default color cycle);
* a color name from a palette, prefixed with the palette's name:

* a name from the `xkcd color survey <https://xkcd.com/color/rgb/>`__;
prefixed with ``'xkcd:'`` (e.g., ``'xkcd:sky blue'``);
* one of ``{'tab:blue', 'tab:orange', 'tab:green',
'tab:red', 'tab:purple', 'tab:brown', 'tab:pink',
'tab:gray', 'tab:olive', 'tab:cyan'}`` which are the Tableau Colors from
the 'T10' categorical palette (which is the default color cycle);
* one of ``{'tabx:blue', 'tabx:orange', 'tabx:red', 'tabx:cyan',
'tabx:green', 'tabx:yellow', 'tabx:purple', 'tabx:pink', 'tabx:brown',
'tabx:gray'}`` which are the colors from the
`new Tableau10 categorical palette
<https://www.tableau.com/about/blog/2016/7/colors-upgrade-tableau-10-\
56782>`__;

* a "CN" color spec, i.e. `'C'` followed by a single digit, which is an index
into the default property cycle (``matplotlib.rcParams['axes.prop_cycle']``);
the indexing occurs at artist creation time and defaults to black if the
Expand Down