如何在Matplotlib的broken_barh图中添加渐变颜色
解决方案:为broken_barh添加水平渐变颜色
broken_barh本身不支持连续渐变填充,因为它的facecolors仅能接受单一颜色或分段颜色列表。要实现目标图表的水平渐变效果,我们可以通过绘制渐变背景并裁剪到条形区域的方式替代。
修改后的完整代码
import matplotlib.pyplot as plt import numpy as np import pandas as pd from matplotlib.lines import Line2D from matplotlib.patches import Rectangle from matplotlib.colors import LinearSegmentedColormap # 定义年份对应颜色 color_2004 = "#5375D4" color_2022 = "#CC5A43" colors = [color_2004, color_2022] * 3 data = { "year": [2004, 2022, 2004, 2022, 2004, 2022], "countries" : ["Sweden", "Sweden", "Denmark", "Denmark", "Norway", "Norway"], "sites": [13,15,4,10,5,8] } df= pd.DataFrame(data) df['pct_change'] = df.groupby('countries', sort=True)['sites'].apply( lambda x: x.pct_change()).to_numpy()*-1 df['ctry_code'] = df.countries.astype(str).str[:2].astype(str).str.upper() df = df.sort_values(['countries','year'], ascending=True ).reset_index(drop=True) df['diff'] = df.groupby(['countries'])['sites'].diff() df['diff'].fillna(df.sites, inplace=True) countries = df.countries.unique() code = df.ctry_code.unique() pct_change = df.pct_change fig, ax = plt.subplots(figsize=(6,5), facecolor = "#FFFFFF") # 自定义从2004到2022的水平渐变色卡 cmap_gradient = LinearSegmentedColormap.from_list('year_gradient', [color_2004, color_2022], N=256) # 替换broken_barh为渐变条形 for i, country in enumerate(countries): # 获取当前国家2022年的sites数值(条形总长度) max_site = df[df['countries'] == country]['sites'].iloc[-1] # 条形的Y轴位置和高度 y_pos = i - 0.2 bar_height = 0.4 # 渐变区域的范围:[x_start, x_end, y_start, y_end] extent = [0, max_site, y_pos, y_pos + bar_height] # 生成渐变数据(横向渐变) gradient = np.linspace(0, 1, 256).reshape(1, -1) # 绘制渐变背景 im = ax.imshow(gradient, extent=extent, cmap=cmap_gradient, aspect='auto', alpha=0.2) # 用矩形裁剪渐变,只保留条形区域 rect = Rectangle((0, y_pos), max_site, bar_height, transform=ax.transData) im.set_clip_path(rect) # 保留原有的散点图 ax.scatter(df.sites, df.countries, marker="D", s=300, color=colors) # 图表样式设置(保持原有逻辑) ax.set(xlim=[0, 16], ylim=[-1, 3]) ax.xaxis.set_ticks(np.arange(0,20,5), labels=[0,5,10,15]) ax.tick_params(axis="x", which="major", length=0, labelsize=14, colors='#C8C9C9') major_ticks = np.arange(0, 16, 1) ax.set_xticks(major_ticks) ax.grid(which='major', axis='x', linestyle='-', alpha=0.4, color="#C8C9C9") ax.set_axisbelow(True) plt.yticks([]) plt.box(False) # 图例设置(保持原有逻辑) labels = ['2004','2022'] lines = [Line2D([0], [0], color=c, marker='D', linestyle='', markersize=12,) for c in [color_2004, color_2022]] plt.figlegend(lines, labels, labelcolor="#C8C9C9", bbox_to_anchor=(0.3, -0.1), loc="lower center", ncols=2, frameon=False, fontsize=12) plt.show()
关键修改说明
- 自定义渐变色卡:用
LinearSegmentedColormap创建从2004蓝色到2022红色的连续渐变。 - 替换broken_barh:
- 对每个国家,计算条形的总长度(2022年的sites值)和Y轴位置。
- 用
imshow绘制横向渐变背景,通过extent匹配条形的位置和尺寸。 - 用
Rectangle补丁裁剪渐变区域,只保留条形范围内的渐变效果。
- 保留原有样式:散点图、坐标轴、图例等设置与原代码一致,仅替换条形绘制逻辑。
内容的提问来源于stack exchange,提问作者ruthpozuelo
相关产品推荐
相关产品推荐

