您可以遍历每个条形位置,并创建一个与条形宽度相同但略低于绘图的彩色矩形。
rectangle 有以下参数:
(x, y), width, height
-
transform=ax.get_xaxis_transform():在 x 方向上,值以 "data coordinates" 测量,这里是 0, 1, 2, ... 用于柱位置;在 y 方向上使用“轴坐标”,从顶部的 1 到绘图区域底部的 0,并在下方的位置使用负数
-
clip_on=False:通常情况下,当某些东西放在绘图区域之外时,它会被剪掉; clip_on=False 会覆盖该行为
-
facecolor=...:内饰颜色
-
edgecolor='black':黑色边框
from matplotlib import pyplot as plt
import pandas as pd
import numpy as np
labels = [*'abcdefghijklmnopqrst']
my_order = pd.DataFrame({'relapse': np.random.randint(11, 51, 20),
'remission': np.random.randint(11, 51, 20),
'cluster': np.random.randint(1, 3, 20)})
fig, ax = plt.subplots(figsize=[15, 5])
width = 0.75
ax.bar(labels, my_order['relapse'], width, label='SAMPLE[0]', color='crimson')
ax.bar(labels, my_order['remission'], width, bottom=my_order['relapse'], label='SAMPLE[1]', color='orange')
ax.set_title('Ratio of cells by patient in each cluster')
legend1 = ax.legend(title='Samples', bbox_to_anchor=(1.01, 0.5), loc='center left')
ax.margins(x=0.01)
color_for_cluster = {1: 'skyblue', 2: 'yellow'}
for i, cluster in enumerate(my_order['cluster']):
ax.add_patch(plt.Rectangle((i - width / 2, -0.1), width, 0.02,
facecolor=color_for_cluster[cluster], edgecolor='black',
transform=ax.get_xaxis_transform(), clip_on=False))
handles = [plt.Rectangle((0, 0), 0, 0, facecolor=color_for_cluster[cluster], edgecolor='black', label=cluster)
for cluster in color_for_cluster]
legend2 = ax.legend(handles=handles, title='Clusters', bbox_to_anchor=(1.01, -0.01), loc='lower left')
ax.add_artist(legend1) # add the legend again, because the second call to ax.legend removes the first legend
fig.tight_layout()
plt.show()
您也可以使用plt.Rectangle((i - 1/2, -0.1), 1, 0.02, ...) 使矩形占据整个宽度。