返回 Skill 列表
extension
分类: 效率与办公无需 API Key

color-accessibility-guide

Colorblind-friendly palettes and accessible visualization design

person作者: TashanworldhubOpenAPI

Color Accessibility Guide

Design data visualizations that are accessible to colorblind readers and follow best practices for clarity, using tested palettes and encoding principles.

Color Vision Deficiency Overview

Approximately 8% of males and 0.5% of females have some form of color vision deficiency (CVD). The most common types:

| Type | Prevalence (Male) | Affected Colors | Commonly Confused | |------|-------------------|-----------------|-------------------| | Deuteranomaly (green-weak) | 5% | Green | Red and green | | Protanomaly (red-weak) | 1% | Red | Red and green | | Deuteranopia (no green) | 1% | Green | Red and green | | Protanopia (no red) | 1% | Red | Red and green | | Tritanopia (no blue) | 0.003% | Blue | Blue and yellow | | Monochromacy | Very rare | All | All colors |

Key takeaway: Never rely solely on a red-green distinction to convey information. About 1 in 12 male readers cannot distinguish them.

Recommended Colorblind-Safe Palettes

Qualitative Palettes (Categorical Data)

Wong (2011) Nature Palette (8 colors)

Widely recommended for scientific publications:

# Wong's colorblind-friendly palette
wong_palette = {
    "black":       "#000000",
    "orange":      "#E69F00",
    "sky_blue":    "#56B4E9",
    "bluish_green":"#009E73",
    "yellow":      "#F0E442",
    "blue":        "#0072B2",
    "vermillion":  "#D55E00",
    "reddish_purple":"#CC79A7"
}

Okabe-Ito Palette

okabe_ito = ["#E69F00", "#56B4E9", "#009E73", "#F0E442",
             "#0072B2", "#D55E00", "#CC79A7", "#000000"]

Tol's Qualitative Palette

# Paul Tol's qualitative palette (up to 12 distinct colors)
tol_qualitative = ["#332288", "#88CCEE", "#44AA99", "#117733",
                   "#999933", "#DDCC77", "#CC6677", "#882255",
                   "#AA4499", "#661100", "#6699CC", "#888888"]

Sequential Palettes (Ordered Data)

For continuous data, use perceptually uniform colormaps:

import matplotlib.pyplot as plt

# Recommended sequential colormaps
# These are perceptually uniform and colorblind-safe:
good_cmaps = ["viridis", "plasma", "inferno", "magma", "cividis"]

# Avoid these (not perceptually uniform, not colorblind-safe):
bad_cmaps = ["jet", "rainbow", "hsv"]  # NEVER use these

# Example usage
import numpy as np
data = np.random.randn(10, 10)
fig, ax = plt.subplots(figsize=(8, 6))
im = ax.imshow(data, cmap="viridis")
plt.colorbar(im)
plt.title("Use viridis, not jet")
plt.savefig("heatmap.pdf", dpi=300, bbox_inches="tight")

Diverging Palettes (Data with Meaningful Center)

# Colorblind-safe diverging palettes
# Blue-to-Red via white (good for temperature, correlation)
import matplotlib.colors as mcolors

# Built-in matplotlib options:
diverging_safe = ["RdBu_r", "PuOr_r", "BrBG"]

# Custom two-color diverging (Tol):
tol_diverging = ["#364B9A", "#4A7BB7", "#6EA6CD", "#98CAE1", "#C2E4EF",
                 "#EAECCC", "#FEDA8B", "#FDB366", "#F67E4B", "#DD3D2D", "#A50026"]

Design Principles for Accessible Visualization

1. Data-Ink Ratio

Edward Tufte's principle: maximize the proportion of ink used to display actual data.

import matplotlib.pyplot as plt

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

# BAD: Low data-ink ratio (chartjunk)
ax1.bar(range(5), [3, 7, 2, 5, 8], color="blue", edgecolor="black",
        linewidth=2)
ax1.set_facecolor("#EEEEEE")
ax1.grid(True, color="white", linewidth=2)
ax1.set_title("Before: Low Data-Ink Ratio")

# GOOD: High data-ink ratio
ax2.bar(range(5), [3, 7, 2, 5, 8], color="#0072B2", edgecolor="none")
ax2.spines["top"].set_visible(False)
ax2.spines["right"].set_visible(False)
ax2.set_title("After: High Data-Ink Ratio")

plt.tight_layout()
plt.savefig("data_ink_ratio.pdf", dpi=300)

2. Redundant Encoding

Never use color as the sole channel for conveying information. Combine color with at least one other visual channel:

| Channel | Examples | |---------|----------| | Shape | Circles, squares, triangles for different groups | | Pattern | Solid, dashed, dotted lines | | Fill pattern | Hatching, cross-hatching for bar charts | | Label | Direct text labels on or near data points | | Position | Separate panels (facets) for each group | | Size | Varying point sizes |

import matplotlib.pyplot as plt

markers = ['o', 's', '^', 'D']  # Different shapes
colors = ['#0072B2', '#D55E00', '#009E73', '#CC79A7']
labels = ['Group A', 'Group B', 'Group C', 'Group D']

fig, ax = plt.subplots(figsize=(8, 6))
for i in range(4):
    ax.scatter(x[i], y[i], c=colors[i], marker=markers[i],
               s=80, label=labels[i], edgecolors='black', linewidth=0.5)

ax.legend()
ax.set_xlabel("X Variable")
ax.set_ylabel("Y Variable")
plt.savefig("redundant_encoding.pdf", dpi=300)

3. Line Style Differentiation

line_styles = ['-', '--', '-.', ':', (0, (3, 1, 1, 1))]
colors = ['#0072B2', '#D55E00', '#009E73', '#CC79A7', '#E69F00']

fig, ax = plt.subplots(figsize=(8, 5))
for i in range(5):
    ax.plot(x, data[i], color=colors[i], linestyle=line_styles[i],
            linewidth=2, label=f"Method {i+1}")

ax.legend()

Checking Your Visualizations

Simulation Tools

| Tool | Platform | URL | |------|----------|-----| | Coblis | Web | color-blindness.com/coblis | | Color Oracle | Desktop (Win/Mac/Linux) | colororacle.org | | Sim Daltonism | macOS | michelf.ca/projects/sim-daltonism | | Colorblindly | Chrome extension | Chrome Web Store | | Matplotlib CVD simulation | Python | See code below |

Programmatic CVD Simulation

from colorspacious import cspace_convert
import numpy as np

def simulate_cvd(rgb_hex, deficiency="deuteranomaly", severity=100):
    """Simulate how a color appears to someone with CVD."""
    # Convert hex to RGB [0,1]
    rgb = np.array([int(rgb_hex[i:i+2], 16)/255 for i in (1, 3, 5)])

    # Convert using colorspacious
    cvd_space = {"name": "sRGB1+CVD",
                 "cvd_type": deficiency,
                 "severity": severity}
    rgb_cvd = cspace_convert(rgb, cvd_space, "sRGB1")
    rgb_cvd = np.clip(rgb_cvd, 0, 1)

    return "#{:02x}{:02x}{:02x}".format(*[int(c*255) for c in rgb_cvd])

# Test your palette
for color in ["#FF0000", "#00FF00", "#0072B2", "#D55E00"]:
    sim = simulate_cvd(color)
    print(f"{color} -> {sim} (deuteranomaly)")

Quick Reference: Do's and Don'ts

| Do | Don't | |----|-------| | Use Wong or Okabe-Ito palettes | Use red vs. green to distinguish categories | | Use viridis/cividis colormaps | Use jet/rainbow colormaps | | Add shape/pattern as redundant encoding | Rely on color alone | | Use direct labels when possible | Force readers to match colors to legend repeatedly | | Test with CVD simulators | Assume your color choices work for everyone | | Use high contrast (WCAG AA: 4.5:1 ratio) | Use light colors on white backgrounds | | Keep maximum 7-8 colors in categorical charts | Use 15+ colors that are impossible to distinguish |