Matplotlib双Y轴颜色设置全攻略:边框、刻度及标签
2025-03-08 15:58:30
Matplotlib 双 Y 轴颜色设置:主轴、次轴、刻度、标签、边框全攻略
碰到了一个 Matplotlib 画图的颜色设置问题。我需要画两个数据集,分别对应左右两个 Y 轴,并用不同的颜色区分。 更进一步,我希望左、右两侧的以下元素都用对应的颜色:
- 左、右垂直边框(spine)
- 刻度(主刻度和次刻度)
- 刻度标签
找了一圈没找到完整的解决方案。用 pandas.plot
的 secondary-y
选项,或者 Matplotlib 的 twinx
来创建次级 Y 轴很容易画出数据,但颜色设置很麻烦。
来看个完整的代码示例:
import matplotlib.pyplot as plt
import matplotlib as mpl
import pandas as pd
df = pd.DataFrame(data={'Series A':[1,1.25,1.5,1.75,2],'Series B':[11,10.75,10.5,10.25,10]})
fig1,ax = plt.subplots()
# 在 ax 上画 Series A
df['Series A'].plot(ax=ax,style='o-',lw=0.5,legend=False,color='b',ylim=(0,3));
ax.set_xlabel('x')
ax.set_ylabel('Y values')
# 生成次级 Y 轴
ax2 = ax.twinx()
# 在 ax2 上画 Series B
df['Series B'].plot(ax=ax2,style='^-',legend=False,lw=0.5,color='g',ylim=(9,12));
plt.show();
到这儿,两个数据集已经正确地画出来了。接下来搞颜色。我加了这两行:
ax.tick_params(axis='y', colors='b',which='both')
ax2.tick_params(axis='y', colors='g',which='both')
这基本搞定了大部分:刻度和刻度标签的颜色都对了。但是边框的颜色没变。
我试过 ax.spines['left'].set_color('orange')
,但没用。这是咋回事?
所以我有两个问题:
- 次级轴的参数访问器是啥(比如,我想改刻度之类的)?
- 怎么让边框的颜色也变了?
问题产生原因分析
核心在于理解 Matplotlib 中主轴 (primary axis) 和次轴 (secondary axis) 的关系,以及如何访问和修改它们的属性。 twinx()
创建的 ax2
并不是 ax
的一个直接子属性,而是一个共享 X 轴的独立坐标轴。ax.spines['left']
只能访问 ax
自身的左边框,对 ax2
无效。
解决方案
1. 访问次级轴属性
ax2
是一个独立的 Axes
对象,它有自己的 spines
、tick_params
等属性。 直接通过 ax2
访问和修改这些属性即可。
2. 设置边框颜色
要设置 ax2
的右边框颜色,直接用 ax2.spines['right'].set_color()
。同理,设置 ax
的左边框用 ax.spines['left'].set_color()
。
3. 设置刻度和刻度标签颜色
上面示例中的 tick_params
使用方法是正确的,直接用就行:
ax.tick_params(axis='y', colors='b',which='both')
ax2.tick_params(axis='y', colors='g',which='both')
which='both'
表示同时修改主刻度和次刻度。
4. 完整代码示例
把上面的方法组合起来,完整的代码如下:
import matplotlib.pyplot as plt
import matplotlib as mpl
import pandas as pd
df = pd.DataFrame(data={'Series A':[1,1.25,1.5,1.75,2],'Series B':[11,10.75,10.5,10.25,10]})
fig1,ax = plt.subplots()
# 在 ax 上画 Series A
df['Series A'].plot(ax=ax,style='o-',lw=0.5,legend=False,color='b',ylim=(0,3));
ax.set_xlabel('x')
ax.set_ylabel('Y values')
# 生成次级 Y 轴
ax2 = ax.twinx()
# 在 ax2 上画 Series B
df['Series B'].plot(ax=ax2,style='^-',legend=False,lw=0.5,color='g',ylim=(9,12));
# 设置颜色
ax.spines['left'].set_color('blue') # 修正:边框用明确的颜色名称
ax.tick_params(axis='y', colors='blue',which='both') # 修正:用明确的颜色名称
ax2.spines['right'].set_color('green') # 修正:用明确的颜色名称
ax2.tick_params(axis='y', colors='green',which='both') #修正:用明确的颜色名称
plt.show();
5. 更精细的控制:分别设置主次刻度
如果需要对主刻度和次刻度进行更精细的控制(比如不同的颜色或大小),可以使用 which='major'
和 which='minor'
分别设置。
# 只设置主刻度颜色
ax.tick_params(axis='y', colors='blue', which='major')
# 只设置次刻度颜色
ax2.tick_params(axis='y', colors='lightgreen', which='minor')
6. 使用 set_tick_params
(不推荐,仅作说明)
虽然也能用 ax2.yaxis.set_tick_params()
,但不推荐。因为 tick_params()
更简洁,而且能同时设置多个属性。set_tick_params()
是旧版本的方法。
# 不推荐!
# ax2.yaxis.set_tick_params(colors='g')
7. 控制 Spine 的可见性
有些时候,咱们可能想要隐藏某一边框。 可以利用set_visible()
这个功能来让某些Spine隐藏起来:
ax2.spines['right'].set_visible(True) #让右侧的spine显示
ax.spines['top'].set_visible(False) #让上方的spine消失
8. 统一修改样式:rcParams
如果需要对全局的绘图样式进行统一修改,可以使用 matplotlib.rcParams
。比如,修改所有线条的默认宽度:
mpl.rcParams['lines.linewidth'] = 2
这会影响之后所有 plot
命令的线条宽度。注意,rcParams
的修改是全局的,会影响整个程序的绘图样式。
9. 进阶: 创建自定义的双Y轴函数.
假如你在很多地方都需要创建类似结构的双Y轴图表, 反复写上面的代码太麻烦。可以考虑封装成一个函数:
import matplotlib.pyplot as plt
import pandas as pd
def plot_dual_y_axis(df, col1, col2, color1='blue', color2='green', fig_size=(10,6)):
"""
绘制双 Y 轴图表,并设置颜色。
参数:
df: 包含数据的 Pandas DataFrame。
col1: 第一个 Y 轴的数据列名。
col2: 第二个 Y 轴的数据列名。
color1: 第一个 Y 轴的颜色。
color2: 第二个 Y 轴的颜色。
返回值:
fig, ax, ax2 (matplotlib figure and axes objects)
"""
fig, ax = plt.subplots(figsize=fig_size)
ax2 = ax.twinx()
df[col1].plot(ax=ax, style='o-', lw=0.5, legend=False, color=color1)
df[col2].plot(ax=ax2, style='^-', legend=False, lw=0.5, color=color2)
ax.spines['left'].set_color(color1)
ax.tick_params(axis='y', colors=color1, which='both')
ax2.spines['right'].set_color(color2)
ax2.tick_params(axis='y', colors=color2, which='both')
return fig, ax, ax2
#使用范例:
df = pd.DataFrame(data={'Series A':[1,1.25,1.5,1.75,2],'Series B':[11,10.75,10.5,10.25,10]})
fig, ax, ax2= plot_dual_y_axis(df, 'Series A', 'Series B', color1='magenta',color2='cyan')
ax.set_xlabel("My X label") # 设置x轴
plt.show()
这个plot_dual_y_axis
函数接受数据、列名和颜色作为参数,直接生成配置好颜色的双Y轴图,干净又便捷。