如何获取Matplotlib分级统计图多边形颜色以添加对比色标签
更简洁的GeoPandas分级统计图对比色标签实现
我用GeoPandas和Matplotlib绘制分级统计图时,需要给每个多边形添加与填充色对比的标签(深色填充用白色字体,浅色用黑色)。原实现通过提取绘图对象的PatchCollection来获取颜色,步骤繁琐,这里提供更简洁清晰的优化方案:
优化后代码
import geopandas as gpd import numpy as np import matplotlib.pyplot as plt from matplotlib.colors import Normalize def get_contrast_color(rgb): # 根据RGB亮度计算对比色:亮度低于0.5用白色,否则用黑色 luminance = 0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2] return (1, 1, 1) if luminance < 0.5 else (0, 0, 0) # 读取示例数据 dfm = gpd.read_file("https://gist.githubusercontent.com/ap-Codkelden/72f988e2bcc90ea3c6c9d6d989d8eb3b/raw/c91927bdb6b199c4dd6df6759200a5a1e4b820f0/obl_sample.geojson") # 计算多边形中心点坐标用于放置标签 dfm['coords'] = dfm.geometry.representative_point().apply(lambda x: x.coords[0]) # 初始化绘图 fig, ax = plt.subplots(1, figsize=(10, 6)) ax.axis('off') ax.set_title('Title', fontdict={'fontsize': 12, 'fontweight': 3}) # 绘制分级统计图,保存返回的绘图对象 gdf_plot = dfm.plot( ax=ax, column='Average', cmap='Blues_r', linewidth=0.5, edgecolor='k', scheme='FisherJenks', k=2, legend=True ) # 获取分箱边界与颜色映射规则 cmap = plt.get_cmap('Blues_r') norm = Normalize(vmin=dfm['Average'].min(), vmax=dfm['Average'].max()) bins = gdf_plot.legend_.get_bounds() # 为每个要素匹配对应的分箱,获取填充色 dfm['bin_idx'] = np.digitize(dfm['Average'], bins[:-1]) - 1 bin_colors = cmap(norm(bins[:-1])) dfm['fill_color'] = bin_colors[dfm['bin_idx']] # 计算标签对比色并添加标签 dfm['text_color'] = dfm['fill_color'].apply(get_contrast_color) for idx, row in dfm.iterrows(): ax.annotate( f"{row['reg_en']}\n{row['Average']:.2f}", xy=row['coords'], horizontalalignment='center', color=row['text_color'], size=9 ) plt.show()
优化亮点
- 避免反向提取颜色:直接通过分箱规则计算每个要素的填充色,无需依赖Axes子元素的内部结构,代码更稳定
- 简化多要素处理:针对多部分多边形,同一要素分箱后颜色一致,无需拆分颜色列表,逻辑更清晰
- 简洁的对比色计算:直接基于RGB值计算相对亮度,省去0-255区间转换步骤
内容的提问来源于stack exchange,提问作者codkelden
相关产品推荐
相关产品推荐

