Creating Custom Continuous Colormaps in Matplotlib: From Fundamentals to Advanced Practices

Dec 02, 2025 · Programming · 13 views · 7.8

Keywords: Matplotlib | Colormap | LinearSegmentedColormap | Data Visualization | Python

Abstract: This article provides an in-depth exploration of various methods for creating custom continuous colormaps in Matplotlib, with a focus on the core mechanisms of LinearSegmentedColormap. By comparing the differences between ListedColormap and LinearSegmentedColormap, it explains in detail how to construct smooth gradient colormaps from red to violet to blue, and demonstrates how to properly integrate colormaps with data normalization and add colorbars. The article also offers practical helper functions and best practice recommendations to help readers avoid common performance pitfalls.

Introduction and Problem Context

In data visualization, colormaps are essential tools for mapping numerical data to colors. Matplotlib, as the most popular plotting library in Python, provides powerful colormap functionality, but users often encounter two core issues: how to create smooth continuous colormaps, and how to correctly display corresponding colorbars. This article uses the example of creating a custom colormap that transitions from red to violet to blue to deeply explore solutions to these problems.

Colormap Type Comparison: Discrete vs. Continuous

Matplotlib primarily offers two types of colormaps: ListedColormap and LinearSegmentedColormap. ListedColormap is based on discrete color lists and is suitable for categorical data, but cannot produce smooth gradient effects. In contrast, LinearSegmentedColormap creates continuous transitions between specified colors through interpolation algorithms, making it more suitable for visualizing continuous numerical data.

The ListedColormap approach used in the original problem:

cmap = matplotlib.colors.ListedColormap(["red","violet","blue"], name='from_list', N=None)

This method can only produce discrete color segments and cannot achieve true smooth gradients. To solve this problem, one must turn to LinearSegmentedColormap.

Core Mechanism of LinearSegmentedColormap

LinearSegmentedColormap defines colormaps through a color dictionary (cdict) containing three channels: 'red', 'green', and 'blue'. Each channel consists of a series of triplets in the format (x, y0, y1), where x is the normalized position (between 0 and 1), and y0 and y1 represent the color intensity values on the left and right sides of that position, respectively.

Here is an example cdict for creating a red-violet-blue gradient:

cdict = {
    'red':   ((0.0, 1.0, 1.0), 
              (0.1, 1.0, 1.0),  # red region
              (0.4, 1.0, 1.0),  # violet region
              (1.0, 0.0, 0.0)), # blue region
    'green': ((0.0, 0.0, 0.0),
              (1.0, 0.0, 0.0)),
    'blue':  ((0.0, 0.0, 0.0),
              (0.1, 0.0, 0.0),  # red region
              (0.4, 1.0, 1.0),  # violet region
              (1.0, 1.0, 0.0))  # blue region
}

Although cdict provides great flexibility, its syntax can be complex for simple gradient needs. For this reason, Matplotlib offers the more concise from_list method.

Simplifying Creation with the from_list Method

The LinearSegmentedColormap.from_list method allows direct creation of colormaps from color lists, with the system automatically performing linear interpolation between colors. Basic usage is as follows:

import matplotlib.colors
cmap = matplotlib.colors.LinearSegmentedColormap.from_list("", ["red","violet","blue"])

For finer control, one can specify the exact numerical positions corresponding to colors. Assuming we want -2 to correspond to red, -1 to violet, and +2 to blue:

import matplotlib.pyplot as plt
import matplotlib.colors

cvals = [-2.0, -1.0, 2.0]
colors = ["red", "violet", "blue"]

# Create normalization object
norm = plt.Normalize(min(cvals), max(cvals))

# Normalize values and pair with colors
tuples = list(zip(map(norm, cvals), colors))

# Create colormap
cmap = matplotlib.colors.LinearSegmentedColormap.from_list("", tuples)

Practical Helper Function: make_colormap

To further simplify the creation process, one can define a helper function make_colormap that accepts a sequence containing color and position information:

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

def make_colormap(seq):
    """Return a LinearSegmentedColormap
    
    Parameters:
    seq: A sequence of floats and RGB tuples. Floats should be increasing and in the interval (0,1).
    """
    seq = [(None,) * 3, 0.0] + list(seq) + [1.0, (None,) * 3]
    cdict = {'red': [], 'green': [], 'blue': []}
    
    for i, item in enumerate(seq):
        if isinstance(item, float):
            r1, g1, b1 = seq[i - 1]
            r2, g2, b2 = seq[i + 1]
            cdict['red'].append([item, r1, r2])
            cdict['green'].append([item, g1, g2])
            cdict['blue'].append([item, b1, b2])
    
    return mcolors.LinearSegmentedColormap('CustomMap', cdict)

# Usage example
c = mcolors.ColorConverter().to_rgb
rvb = make_colormap([
    c('red'), c('violet'), 0.33,
    c('violet'), c('blue'), 0.66,
    c('blue')
])

Complete Visualization Implementation

When applying custom colormaps to actual plots, proper normalization and colorbar setup are essential:

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

# Generate example data
N = 1000
x = np.random.uniform(-2, 2, size=N)
y = np.random.uniform(-2, 2, size=N)
colors = np.random.uniform(-2, 2, size=N)

# Create colormap
cmap = matplotlib.colors.LinearSegmentedColormap.from_list(
    "RedVioletBlue", ["red", "violet", "blue"]
)

# Create normalization object
norm = plt.Normalize(-2, 2)

# Create scatter plot
plt.scatter(x, y, c=colors, cmap=cmap, norm=norm, s=50, alpha=0.8)

# Add colorbar
plt.colorbar(label='Value')
plt.xlabel('X Axis')
plt.ylabel('Y Axis')
plt.title('Custom Colormap Visualization')
plt.show()

Performance Optimization and Best Practices

The original approach using a plt.plot loop to draw each point has significant performance issues:

for i in range(0, len(array_dg)):
    plt.plot(array_dg[i], markers.next(), alpha=alpha[i], c=colors.next())

This method creates a new plotting object with each call to plt.plot, causing performance to degrade sharply with many data points. The correct approach is to use plt.scatter, which can plot all points at once and assign different colors to each point:

plt.scatter(x, y, c=colors, cmap=cmap, norm=norm, s=50, alpha=0.8)

This method not only performs better but also integrates more effectively with Matplotlib's colormap system, automatically handling color mapping and colorbar display.

Conclusion

Creating custom continuous colormaps is an important skill in data visualization. By understanding how LinearSegmentedColormap works, mastering the from_list method and cdict format, and using plt.scatter instead of loop-based plotting, users can create both aesthetically pleasing and efficient visualizations. The methods introduced in this article are not limited to red-violet-blue gradients but can be extended to any color combination, providing powerful tools for scientific computing and data visualization.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.