7. 装饰器 + matplotlib 多图表¶
演示如何用装饰器让同一绘图函数自动用不同色带渲染多种图表。
方式一:single 模式 — 多组柱状图¶
每个色带独立弹窗展示柱状图。
In [1]:
Copied!
import numpy as np
import matplotlib.pyplot as plt
from multicolor import cmap, batch_cmaps
# 模拟数据
categories = ["Q1", "Q2", "Q3", "Q4"]
values = [23, 45, 56, 78]
x = np.arange(len(categories))
@batch_cmaps(["Viridis", "Plasma", "Inferno"])
def show_bar_chart(cmap_obj, ax=None):
colors = cmap_obj(np.linspace(0, 1, len(values)))
if ax is None:
fig, ax = plt.subplots(figsize=(6, 4))
ax.bar(categories, values, color=colors)
ax.set_title(f"Seasonal Sales ({cmap_obj.name})")
ax.set_ylabel("Revenue")
show_bar_chart()
import numpy as np
import matplotlib.pyplot as plt
from multicolor import cmap, batch_cmaps
# 模拟数据
categories = ["Q1", "Q2", "Q3", "Q4"]
values = [23, 45, 56, 78]
x = np.arange(len(categories))
@batch_cmaps(["Viridis", "Plasma", "Inferno"])
def show_bar_chart(cmap_obj, ax=None):
colors = cmap_obj(np.linspace(0, 1, len(values)))
if ax is None:
fig, ax = plt.subplots(figsize=(6, 4))
ax.bar(categories, values, color=colors)
ax.set_title(f"Seasonal Sales ({cmap_obj.name})")
ax.set_ylabel("Revenue")
show_bar_chart()
方式二:single 模式 — 多组折线图¶
In [2]:
Copied!
import numpy as np
import matplotlib.pyplot as plt
from multicolor import cmap, batch_cmaps
np.random.seed(42)
x = np.linspace(0, 10, 50)
@batch_cmaps(["Cividis", "Coolwarm", "RdYlGn"])
def show_line_chart(cmap_obj, ax=None):
if ax is None:
fig, ax = plt.subplots(figsize=(6, 4))
# 每条线用色带中一个颜色
colors = cmap_obj(np.linspace(0, 1, 5))
for i in range(5):
y = np.sin(x + i * 0.5) + np.random.randn(50) * 0.1
ax.plot(x, y, color=colors[i], linewidth=2, label=f"Line {i+1}")
ax.set_title(f"Multi-line Plot ({cmap_obj.name})")
ax.set_xlabel("Time")
ax.set_ylabel("Value")
ax.legend(fontsize="small", loc="upper right")
show_line_chart()
import numpy as np
import matplotlib.pyplot as plt
from multicolor import cmap, batch_cmaps
np.random.seed(42)
x = np.linspace(0, 10, 50)
@batch_cmaps(["Cividis", "Coolwarm", "RdYlGn"])
def show_line_chart(cmap_obj, ax=None):
if ax is None:
fig, ax = plt.subplots(figsize=(6, 4))
# 每条线用色带中一个颜色
colors = cmap_obj(np.linspace(0, 1, 5))
for i in range(5):
y = np.sin(x + i * 0.5) + np.random.randn(50) * 0.1
ax.plot(x, y, color=colors[i], linewidth=2, label=f"Line {i+1}")
ax.set_title(f"Multi-line Plot ({cmap_obj.name})")
ax.set_xlabel("Time")
ax.set_ylabel("Value")
ax.legend(fontsize="small", loc="upper right")
show_line_chart()
方式三:grid 模式 — 所有折线图在一张图上¶
In [3]:
Copied!
import numpy as np
import matplotlib.pyplot as plt
from multicolor import cmap, batch_cmaps
np.random.seed(42)
x = np.linspace(0, 10, 50)
@batch_cmaps(
query_func=lambda: cmap.names(cmap_type="diverging", is_custom=False),
layout="grid",
cols=2,
)
def show_diverging_lines(cmap_obj, ax=None):
colors = cmap_obj(np.linspace(0, 1, 5))
for i in range(5):
y = np.sin(x + i * 0.8) + np.random.randn(50) * 0.1
ax.plot(x, y, color=colors[i], linewidth=2)
ax.set_title(cmap_obj.name, fontsize=10)
show_diverging_lines()
import numpy as np
import matplotlib.pyplot as plt
from multicolor import cmap, batch_cmaps
np.random.seed(42)
x = np.linspace(0, 10, 50)
@batch_cmaps(
query_func=lambda: cmap.names(cmap_type="diverging", is_custom=False),
layout="grid",
cols=2,
)
def show_diverging_lines(cmap_obj, ax=None):
colors = cmap_obj(np.linspace(0, 1, 5))
for i in range(5):
y = np.sin(x + i * 0.8) + np.random.randn(50) * 0.1
ax.plot(x, y, color=colors[i], linewidth=2)
ax.set_title(cmap_obj.name, fontsize=10)
show_diverging_lines()
方式四:grid 模式 — 分组柱状图对比¶
比较不同类型色带在同一数据上的视觉效果。
In [4]:
Copied!
import numpy as np
import matplotlib.pyplot as plt
from multicolor import cmap, batch_cmaps
np.random.seed(42)
groups = ["A", "B", "C", "D", "E"]
values1 = [20, 35, 30, 35, 27]
values2 = [25, 32, 34, 20, 25]
x = np.arange(len(groups))
width = 0.35
@batch_cmaps(["Viridis", "RdYlGn", "Terrain"])
def show_grouped_bars(cmap_obj, ax=None):
if ax is None:
fig, ax = plt.subplots(figsize=(8, 5))
# 从色带中取 5 个均匀分布的颜色
cmap_colors = cmap_obj(np.linspace(0, 1, 5))
ax.bar(x - width / 2, values1, width, color=cmap_colors, label="Group 1")
ax.bar(x + width / 2, values2, width, color=cmap_colors[::-1], label="Group 2")
ax.set_title(f"Comparison ({cmap_obj.name})")
ax.set_xticks(x)
ax.set_xticklabels(groups)
ax.legend(fontsize="small")
show_grouped_bars()
import numpy as np
import matplotlib.pyplot as plt
from multicolor import cmap, batch_cmaps
np.random.seed(42)
groups = ["A", "B", "C", "D", "E"]
values1 = [20, 35, 30, 35, 27]
values2 = [25, 32, 34, 20, 25]
x = np.arange(len(groups))
width = 0.35
@batch_cmaps(["Viridis", "RdYlGn", "Terrain"])
def show_grouped_bars(cmap_obj, ax=None):
if ax is None:
fig, ax = plt.subplots(figsize=(8, 5))
# 从色带中取 5 个均匀分布的颜色
cmap_colors = cmap_obj(np.linspace(0, 1, 5))
ax.bar(x - width / 2, values1, width, color=cmap_colors, label="Group 1")
ax.bar(x + width / 2, values2, width, color=cmap_colors[::-1], label="Group 2")
ax.set_title(f"Comparison ({cmap_obj.name})")
ax.set_xticks(x)
ax.set_xticklabels(groups)
ax.legend(fontsize="small")
show_grouped_bars()
方式五:ColormapRenderer 批量导出¶
不用弹窗,直接导出为文件。
In [5]:
Copied!
import os
import numpy as np
import matplotlib.pyplot as plt
from multicolor.render import ColormapRenderer
from multicolor import cmap
# 获取色带
items = cmap.list(cmap_type="sequential", tag="common", is_custom=False)
cmaps = [(name, cm) for _, name, cm in items]
# 用 render_grid 预览
fig, axes = ColormapRenderer.render_grid(cmaps, cols=3, size_per_colormap=(3, 1.5))
plt.show()
# 批量导出为 PNG
outdir = os.path.join(os.getcwd(), "cmap_comparisons")
col = cmap.collection(cmap_type="sequential", tag="common", is_custom=False)
col.export_images(outdir, orientation="horizontal", size=(4, 1), dpi=150)
print(f"Exported to {outdir}:")
for f in sorted(os.listdir(outdir)):
print(f" {f}")
plt.close("all")
import os
import numpy as np
import matplotlib.pyplot as plt
from multicolor.render import ColormapRenderer
from multicolor import cmap
# 获取色带
items = cmap.list(cmap_type="sequential", tag="common", is_custom=False)
cmaps = [(name, cm) for _, name, cm in items]
# 用 render_grid 预览
fig, axes = ColormapRenderer.render_grid(cmaps, cols=3, size_per_colormap=(3, 1.5))
plt.show()
# 批量导出为 PNG
outdir = os.path.join(os.getcwd(), "cmap_comparisons")
col = cmap.collection(cmap_type="sequential", tag="common", is_custom=False)
col.export_images(outdir, orientation="horizontal", size=(4, 1), dpi=150)
print(f"Exported to {outdir}:")
for f in sorted(os.listdir(outdir)):
print(f" {f}")
plt.close("all")
Exported to /home/runner/work/multicolor/multicolor/docs/examples/cmap_comparisons: Cividis.png Inferno.png Jet.png Magma.png Plasma.png Turbo.png Viridis.png