How to Change Colors in Matplotlib

Color is one of the most powerful tools in data visualization. The right color choices make your plots intuitive and accessible, while poor choices can mislead viewers or make your data...

Key Insights

  • Matplotlib supports multiple color specification methods including named colors, hex codes, RGB tuples, and colormaps—choose based on your workflow and precision needs
  • The default color cycle can be customized globally using set_prop_cycle() to maintain consistent branding across all visualizations in your project
  • For accessibility and scientific accuracy, use perceptually uniform colormaps like ‘viridis’ or ‘cividis’ instead of rainbow colormaps like ‘jet’

Introduction to Matplotlib Colors

Color is one of the most powerful tools in data visualization. The right color choices make your plots intuitive and accessible, while poor choices can mislead viewers or make your data incomprehensible. Matplotlib provides extensive color customization options, from simple named colors to sophisticated colormaps for representing continuous data.

Understanding Matplotlib’s color system is essential because different use cases demand different approaches. A simple line plot might need just a few distinct colors, while a heatmap requires a continuous colormap that accurately represents data gradients. Let’s start with a comparison:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))

# Default colors
ax1.plot(x, y1, label='sin(x)')
ax1.plot(x, y2, label='cos(x)')
ax1.set_title('Default Colors')
ax1.legend()

# Customized colors
ax2.plot(x, y1, color='#2E86AB', linewidth=2, label='sin(x)')
ax2.plot(x, y2, color='#A23B72', linewidth=2, label='cos(x)')
ax2.set_title('Custom Colors')
ax2.legend()

plt.tight_layout()
plt.show()

This example immediately demonstrates the impact of intentional color choices. The customized version uses specific hex codes that provide better contrast and visual appeal.

Basic Color Specification Methods

Matplotlib accepts colors in several formats, each with its own advantages. Named colors are convenient and readable in code. Matplotlib supports all CSS4 named colors—148 options including ‘red’, ‘steelblue’, and ‘darkseagreen’. For precise control, use hex codes like ‘#FF5733’. For programmatic color generation, RGB or RGBA tuples work best, with values ranging from 0 to 1.

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(5)
y_values = [np.random.randint(10, 50, 5) for _ in range(4)]

fig, ax = plt.subplots(figsize=(10, 6))

# Named color
ax.plot(x, y_values[0], marker='o', color='crimson', 
        linewidth=2, label='Named: crimson')

# Hex code
ax.plot(x, y_values[1], marker='s', color='#2A9D8F', 
        linewidth=2, label='Hex: #2A9D8F')

# RGB tuple
ax.plot(x, y_values[2], marker='^', color=(0.9, 0.6, 0.0), 
        linewidth=2, label='RGB: (0.9, 0.6, 0.0)')

# RGBA tuple (with transparency)
ax.plot(x, y_values[3], marker='D', color=(0.4, 0.2, 0.6, 0.7), 
        linewidth=2, label='RGBA: (0.4, 0.2, 0.6, 0.7)')

ax.legend()
ax.set_xlabel('X Values')
ax.set_ylabel('Y Values')
ax.set_title('Color Specification Methods')
plt.show()

Choose named colors for quick prototyping, hex codes when matching brand guidelines, and RGB tuples when generating colors algorithmically.

Changing Colors for Common Plot Elements

Different plot types expose different color parameters. Understanding which parameter controls which element prevents frustration and saves time.

import matplotlib.pyplot as plt
import numpy as np

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))

# Bar chart with customized colors
categories = ['A', 'B', 'C', 'D', 'E']
values = [23, 45, 56, 78, 32]

bars = ax1.bar(categories, values, 
               color='#E63946',           # Fill color
               edgecolor='#1D3557',       # Border color
               linewidth=2)

# Color individual bars differently
bars[2].set_color('#F4A261')

ax1.set_title('Bar Chart Color Customization')
ax1.set_facecolor('#F1FAEE')  # Background color

# Scatter plot with customized colors
np.random.seed(42)
x = np.random.randn(100)
y = np.random.randn(100)

ax2.scatter(x, y, 
            c='#457B9D',              # Marker face color
            edgecolors='#1D3557',     # Marker edge color
            linewidths=1.5,
            s=100,                     # Marker size
            alpha=0.6)

ax2.set_title('Scatter Plot Color Customization')
ax2.set_facecolor('#F1FAEE')
ax2.grid(True, alpha=0.3, color='#A8DADC')

plt.tight_layout()
plt.show()

The key parameters are color or c for primary colors, edgecolor or edgecolors for borders, and facecolor for filled areas. Note the plural forms for scatter plots—Matplotlib’s API isn’t perfectly consistent here.

Working with Color Cycles and Palettes

When plotting multiple data series, Matplotlib cycles through a default color palette. You can customize this cycle to match your requirements or branding.

import matplotlib.pyplot as plt
import numpy as np
from cycler import cycler

# Create sample data
x = np.linspace(0, 10, 100)
data_series = [np.sin(x + i*0.5) for i in range(5)]

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))

# Default color cycle
for i, y in enumerate(data_series):
    ax1.plot(x, y, linewidth=2, label=f'Series {i+1}')
ax1.set_title('Default Color Cycle')
ax1.legend()

# Custom color cycle
custom_colors = ['#264653', '#2A9D8F', '#E9C46A', '#F4A261', '#E76F51']
ax2.set_prop_cycle(cycler(color=custom_colors))

for i, y in enumerate(data_series):
    ax2.plot(x, y, linewidth=2, label=f'Series {i+1}')
ax2.set_title('Custom Color Cycle')
ax2.legend()

plt.tight_layout()
plt.show()

You can also set the color cycle globally for all subsequent plots:

plt.rc('axes', prop_cycle=cycler(color=custom_colors))

This approach ensures consistency across all visualizations in your analysis or report.

Using Colormaps for Continuous Data

Colormaps are essential for representing continuous data in heatmaps, contour plots, and scatter plots where color encodes a third variable. Matplotlib categorizes colormaps into sequential (for ordered data), diverging (for data with a meaningful center), and qualitative (for categorical data).

import matplotlib.pyplot as plt
import numpy as np

# Generate sample data
data = np.random.randn(10, 10)
x = np.random.rand(100)
y = np.random.rand(100)
colors = np.random.rand(100)

fig, axes = plt.subplots(2, 2, figsize=(12, 10))

# Sequential colormap (viridis)
im1 = axes[0, 0].imshow(data, cmap='viridis')
axes[0, 0].set_title('Sequential: viridis')
plt.colorbar(im1, ax=axes[0, 0])

# Sequential colormap (plasma)
im2 = axes[0, 1].imshow(data, cmap='plasma')
axes[0, 1].set_title('Sequential: plasma')
plt.colorbar(im2, ax=axes[0, 1])

# Diverging colormap (coolwarm)
im3 = axes[1, 0].imshow(data, cmap='coolwarm')
axes[1, 0].set_title('Diverging: coolwarm')
plt.colorbar(im3, ax=axes[1, 0])

# Scatter with colormap
scatter = axes[1, 1].scatter(x, y, c=colors, cmap='viridis', 
                              s=100, edgecolors='black', linewidths=0.5)
axes[1, 1].set_title('Scatter with colormap')
plt.colorbar(scatter, ax=axes[1, 1])

plt.tight_layout()
plt.show()

The viridis colormap is Matplotlib’s default for good reason—it’s perceptually uniform, prints well in grayscale, and is accessible to colorblind viewers.

Advanced Color Customization

For specialized needs, create custom colormaps or normalize color scales to emphasize specific data ranges.

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import LinearSegmentedColormap, Normalize

# Create custom colormap
colors_list = ['#0D1B2A', '#1B263B', '#415A77', '#778DA9', '#E0E1DD']
n_bins = 100
cmap = LinearSegmentedColormap.from_list('custom', colors_list, N=n_bins)

# Generate 2D data
x = np.linspace(-3, 3, 100)
y = np.linspace(-3, 3, 100)
X, Y = np.meshgrid(x, y)
Z = np.exp(-(X**2 + Y**2)/3) * np.cos(X) * np.sin(Y)

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))

# Custom colormap
im1 = ax1.contourf(X, Y, Z, levels=20, cmap=cmap)
ax1.set_title('Custom Colormap')
plt.colorbar(im1, ax=ax1)

# Custom normalization (emphasize values near zero)
norm = Normalize(vmin=-0.3, vmax=0.3)
im2 = ax2.contourf(X, Y, Z, levels=20, cmap='RdBu_r', norm=norm)
ax2.set_title('Custom Normalization')
plt.colorbar(im2, ax=ax2)

plt.tight_layout()
plt.show()

Custom colormaps are valuable for matching organizational branding or creating visualizations for specific domains where certain color associations are expected.

Best Practices and Accessibility

Effective color use requires considering your audience. Approximately 8% of men and 0.5% of women have some form of color vision deficiency. Use colorblind-friendly palettes and avoid relying solely on color to convey information.

import matplotlib.pyplot as plt
import numpy as np

# Sample data
categories = ['Category A', 'Category B', 'Category C', 'Category D']
values1 = [25, 40, 30, 35]
values2 = [30, 35, 25, 40]

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))

# Problematic: red-green combination
x = np.arange(len(categories))
ax1.bar(x - 0.2, values1, 0.4, color='red', label='Group 1')
ax1.bar(x + 0.2, values2, 0.4, color='green', label='Group 2')
ax1.set_title('Problematic: Red-Green')
ax1.set_xticks(x)
ax1.set_xticklabels(categories)
ax1.legend()

# Colorblind-friendly alternative
ax2.bar(x - 0.2, values1, 0.4, color='#0173B2', label='Group 1')
ax2.bar(x + 0.2, values2, 0.4, color='#DE8F05', label='Group 2')
ax2.set_title('Colorblind-Friendly: Blue-Orange')
ax2.set_xticks(x)
ax2.set_xticklabels(categories)
ax2.legend()

plt.tight_layout()
plt.show()

Additional best practices include using sufficient contrast (especially against backgrounds), limiting your palette to 5-7 distinct colors in a single plot, and testing your visualizations in grayscale to ensure information isn’t lost. Tools like ColorBrewer and the seaborn library provide pre-designed accessible color palettes.

Mastering color in Matplotlib transforms your visualizations from merely functional to genuinely communicative. Start with these fundamentals, experiment with different approaches, and always consider your audience’s needs.

Liked this? There's more.

Every week: one practical technique, explained simply, with code you can use immediately.