You may use the HSV system to obtain differently saturated and luminated colors for the same hue. Suppose you have at most 10 categories, then the tab10 map can be used to get a certain number of base colors. From those you can choose a couple of lighter shades for the subcategories.

The following would be a function categorical_cmap, which takes as input the number of categories (nc) and the number of subcategories (nsc) and returns a colormap with nc*nsc different colors, where for each category there are nsc colors of same hue.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors

def categorical_cmap(nc, nsc, cmap="tab10", continuous=False):
    if nc > plt.get_cmap(cmap).N:
        raise ValueError("Too many categories for colormap.")
    if continuous:
        ccolors = plt.get_cmap(cmap)(np.linspace(0,1,nc))
    else:
        ccolors = plt.get_cmap(cmap)(np.arange(nc, dtype=int))
    cols = np.zeros((nc*nsc, 3))
    for i, c in enumerate(ccolors):
        chsv = matplotlib.colors.rgb_to_hsv(c[:3])
        arhsv = np.tile(chsv,nsc).reshape(nsc,3)
        arhsv[:,1] = np.linspace(chsv[1],0.25,nsc)
        arhsv[:,2] = np.linspace(chsv[2],1,nsc)
        rgb = matplotlib.colors.hsv_to_rgb(arhsv)
        cols[i*nsc:(i+1)*nsc,:] = rgb       
    cmap = matplotlib.colors.ListedColormap(cols)
    return cmap

c1 = categorical_cmap(4, 3, cmap="tab10")
plt.scatter(np.arange(4*3),np.ones(4*3)+1, c=np.arange(4*3), s=180, cmap=c1)

c2 = categorical_cmap(2, 5, cmap="tab10")
plt.scatter(np.arange(10),np.ones(10), c=np.arange(10), s=180, cmap=c2)

c3 = categorical_cmap(5, 4, cmap="tab10")
plt.scatter(np.arange(20),np.ones(20)-1, c=np.arange(20), s=180, cmap=c3)    

plt.margins(y=0.3)
plt.xticks([])
plt.yticks([0,1,2],["(5, 4)", "(2, 5)", "(4, 3)"])
plt.show()

Answer from ImportanceOfBeingErnest on Stack Overflow
🌐
Matplotlib
matplotlib.org › stable › users › explain › colors › colormaps.html
Choosing Colormaps in Matplotlib — Matplotlib 3.11.2 documentation
plot_color_gradients('Qualitative', ['Pastel1', 'Pastel2', 'Paired', 'Accent', 'okabe_ito', 'Dark2', 'Set1', 'Set2', 'Set3', 'tab10', 'tab20', 'tab20b', 'tab20c']) Some of the miscellaneous colormaps have particular uses for which they have been created. For example, gist_earth, ocean, and terrain all seem to be created for plotting topography (green/brown) and water depths (blue) together.
Top answer
1 of 1
33

You may use the HSV system to obtain differently saturated and luminated colors for the same hue. Suppose you have at most 10 categories, then the tab10 map can be used to get a certain number of base colors. From those you can choose a couple of lighter shades for the subcategories.

The following would be a function categorical_cmap, which takes as input the number of categories (nc) and the number of subcategories (nsc) and returns a colormap with nc*nsc different colors, where for each category there are nsc colors of same hue.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors

def categorical_cmap(nc, nsc, cmap="tab10", continuous=False):
    if nc > plt.get_cmap(cmap).N:
        raise ValueError("Too many categories for colormap.")
    if continuous:
        ccolors = plt.get_cmap(cmap)(np.linspace(0,1,nc))
    else:
        ccolors = plt.get_cmap(cmap)(np.arange(nc, dtype=int))
    cols = np.zeros((nc*nsc, 3))
    for i, c in enumerate(ccolors):
        chsv = matplotlib.colors.rgb_to_hsv(c[:3])
        arhsv = np.tile(chsv,nsc).reshape(nsc,3)
        arhsv[:,1] = np.linspace(chsv[1],0.25,nsc)
        arhsv[:,2] = np.linspace(chsv[2],1,nsc)
        rgb = matplotlib.colors.hsv_to_rgb(arhsv)
        cols[i*nsc:(i+1)*nsc,:] = rgb       
    cmap = matplotlib.colors.ListedColormap(cols)
    return cmap

c1 = categorical_cmap(4, 3, cmap="tab10")
plt.scatter(np.arange(4*3),np.ones(4*3)+1, c=np.arange(4*3), s=180, cmap=c1)

c2 = categorical_cmap(2, 5, cmap="tab10")
plt.scatter(np.arange(10),np.ones(10), c=np.arange(10), s=180, cmap=c2)

c3 = categorical_cmap(5, 4, cmap="tab10")
plt.scatter(np.arange(20),np.ones(20)-1, c=np.arange(20), s=180, cmap=c3)    

plt.margins(y=0.3)
plt.xticks([])
plt.yticks([0,1,2],["(5, 4)", "(2, 5)", "(4, 3)"])
plt.show()

🌐
Matplotlib
matplotlib.org › stable › gallery › color › colormap_reference.html
Colormap reference — Matplotlib 3.11.2 documentation
import matplotlib.pyplot as plt ... 'hsv']), ('Qualitative', [ 'Pastel1', 'Pastel2', 'Paired', 'Accent', 'okabe_ito', 'Dark2', 'Set1', 'Set2', 'Set3', 'tab10', 'tab20', 'tab20b', 'tab20c']), ('Miscellaneous', [ 'flag', 'prism', 'ocean', 'gist_earth', 'terrain', 'gist_stern', ...
🌐
Chrisholdgraf
chrisholdgraf.com › matplotlib › tutorials › colors › colormaps.html
Colormaps in Matplotlib — Matplotlib 2.0.0b1.post7580.dev0+ge487118 documentation
cmaps['Qualitative'] = ['Pastel1', 'Pastel2', 'Paired', 'Accent', 'Dark2', 'Set1', 'Set2', 'Set3', 'tab10', 'tab20', 'tab20b', 'tab20c'] Some of the miscellaneous colormaps have particular uses for which they have been created. For example, gist_earth, ocean, and terrain all seem to be created for plotting topography (green/brown) and water depths (blue) together.
🌐
Medium
medium.com › @lazychiko › on-traits-colormap-texture-8db9eb94f9b2
On Traits: Colormap & Texture. In this article, I want to outline… | by Chiko | Medium
September 5, 2023 - Note: For colors, I used the default colormaps provided by Matplotlib. The ones I used are: {Pastel2, Purples, Set3, bwr, gist_ncar, flag, bone, jet, accent, coolwarm, binary, twilight, rainbow, seismic, gist_rainbow, gist_heat, hsv, RdYlGn, terriain, tab10, PuBu, RdGy, cool, PubuGn, cubehelix, pink, ocean, nipy_spectral}
🌐
Medium
medium.com › @kevinrioharris › enhancing-data-visualizations-with-color-palettes-in-matplotlib-0a39e70f8dfc
Enhancing Data Visualizations with Color Palettes in Matplotlib | by Kevin Rio Harristyando | Medium
November 13, 2024 - import matplotlib.pyplot as plt import numpy as np import seaborn as sns # Sample data for bar charts categories = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'] values = np.random.rand(10) # Define the popular qualitative palettes qualitative_palettes = ['tab10', 'Set1', 'Set2', 'Paired', 'Accent'] # Create a 3x2 grid of subplots fig, axes = plt.subplots(3, 2, figsize=(15, 12)) axes = axes.flatten() # Plot each qualitative palette on a separate bar plot for i, palette in enumerate(qualitative_palettes): sns.barplot(x=categories, y=values, hue=categories, palette=palette, ax=axes[i]) axes[i].set_title(f'palette = {palette}') axes[i].set_ylim(0, 1) # Remove the last (empty) subplot axes[5].axis('off') # Adjust layout for better spacing plt.subplots_adjust(wspace=0.15, hspace=0.3) plt.show()
🌐
GitHub
github.com › kavli-ntnu › MINI2P_toolbox › blob › main › Analysis › +CMP_WJ › tab10.m
MINI2P_toolbox/Analysis/+CMP_WJ/tab10.m at main · kavli-ntnu/MINI2P_toolbox
% VEGA10/TAB10 is the default Line Color Order for MatPlotLib 2 and 3. % % MATLAB axes ColorOrder (note that this is NOT the axes COLORMAP): % <https://www.mathworks.com/help/matlab/creating_plots/defining-the-color-of-lines-for-plotting.html> % <https://www.mathworks.com/help/matlab/graphics_transition/why-are-plot-lines-different-colors.html> % %% Examples %% % %%% PLOT using matrices: % N = 10; % axes('ColorOrder',tab10(N),'NextPlot','replacechildren') % X = linspace(0,pi*3,1000); % Y = bsxfun(@(x,n)sqrt(n)*sin(x+2*n*pi/N), X(:), 1:N); % plot(X,Y, 'linewidth',4) % %%% PLOT in a loop: % N = 10; % set(0,'DefaultAxesColorOrder',tab10(N)) % X = linspace(0,pi*3,1000); % Y = bsxfun(@(x,n)sqrt(n)*sin(x+2*n*pi/N), X(:), 1:N); % for n = 1:N ·
Author: kavli-ntnu
🌐
Bendalab
bendalab.github.io › plottools › colors
Colors - plottools
This is matplotlib's tableau palette, the default in newer matplotlib versions, also known as tab10.
Find elsewhere
🌐
Ancisoft
ancisoft.com › blog › what-are-the-hex-codes-of-matplotlib-tab10-palette
What Are the Hex Codes of Matplotlib's Tab10 Palette? (Including RGB Values & How to Find Hex Codes for Any Named Color) — ancisoft.com
Matplotlib’s Tab10 palette is a qualitative (categorical) color palette designed for clarity and accessibility. It is part of the "tab" family of palettes (including Tab20, Tab20b, Tab20c), which were inspired by Tableau’s color schemes.
🌐
Readthedocs
cmap-docs.readthedocs.io › catalog › qualitative › seaborn:tab10
seaborn:tab10 - cmap
from cmap import Colormap cm = Colormap('seaborn:tab10') # case insensitive · seaborn:tab10 · seaborn:tab10 ·
🌐
GitHub
github.com › matplotlib › matplotlib › blob › main › lib › matplotlib › _cm.py
matplotlib/lib/matplotlib/_cm.py at main · matplotlib/matplotlib
_tab10_data = ( (0.12156862745098039, 0.4666666666666667, 0.7058823529411765 ), # 1f77b4 · (1.0, 0.4980392156862745, 0.054901960784313725), # ff7f0e · (0.17254901960784313, 0.6274509803921569, 0.17254901960784313 ), # 2ca02c ·
Author: matplotlib
🌐
Seaborn
seaborn.pydata.org › tutorial › color_palettes.html
Choosing color palettes — seaborn 0.13.2 documentation
These colors have the same ordering as the default matplotlib color palette, "tab10", but they are a bit less intense.
🌐
Matplotlib
matplotlib.org › stable › gallery › color › color_demo.html
Color Demo — Matplotlib 3.11.2 documentation
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 · the ...
🌐
Julia Programming Language
discourse.julialang.org › specific domains › visualization
Issues setting palette to matlplotlib's "tab10" colors - Visualization - Julia Programming Language
May 3, 2020 - Hello, I’ve been trying to plot curves with the colors of matplotlib’s palette :tab10 but I can’t find the solution, even after removing and reinstalling Plots and ColorSchemes. Here are the desired colors : When I run palette(:auto) , I do obtain a 17-element Vector{RGBA{Float64}}, and it’s correctly plotted in the Plot panel of Juno.
🌐
MathWorks
mathworks.com › matlabcentral › fileexchange › 62729-matplotlib-perceptually-uniform-colormaps
Matplotlib "Perceptually Uniform" Colormaps - File Exchange - MATLAB Central
2 weeks ago - MatPlotLib's default linear lightness colormap VIRIDIS and distinctive line colororder TAB10 · Stephen23 · Version 2.1.10 (881 KB) 8.7K Downloads · 4.90/5 (18) 14 Oct 2026 · Download Toggle Dropdown · Requires R2026b and later. Learn more · Share 'Matplotlib "Perceptually Uniform" Colormaps' Open in File Exchange ·
🌐
W3Schools
w3schools.com › python › trypython.asp
W3Schools online PYTHON editor
The W3Schools online code editor allows you to edit code and view the result in your browser
🌐
Noga H. Rotman
r02b.github.io › seaborn_palettes
Seaborn Color Palettes and How to Use Them | Noga H. Rotman
November 8, 2022 - I use the three palette classes seaborn uses in their documentation - qualitative, sequential and diverging, as well as matplotlib’s miscellaneous. Best for categorical data, as they vary mostly in the hue component (the most noticeable exceptions here are tab20b and tab20c). This pattern of variations creates different colors with very similar luminosity and saturation, so the palette looks cohesive, and there is no “special” color that stands out compared to the others. The matlab default palette we all know and love is called tab10, and is also the default palette for most seaborn functions.
🌐
Kanaries
docs.kanaries.net › topics › Matplotlib › examples-matplotlib-cmaps
Matplotlib Colormaps: Interactive Explorer and Complete Gallery – Kanaries
August 19, 2026 - Never use a qualitative map for continuous data. tab10 on a heatmap creates bands that are not in the data. Never use a diverging map without centering the norm. plt.imshow(data, cmap="RdBu") on data from 3 to 90 puts the white midpoint at 46.5, which reads as "neutral" even though nothing is neutral there. Use TwoSlopeNorm(vcenter=0) instead. from matplotlib.colors import TwoSlopeNorm norm = TwoSlopeNorm(vmin=data.min(), vcenter=0, vmax=data.max()) plt.imshow(data, cmap="RdBu_r", norm=norm) plt.colorbar()