You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pygal柱状图:如何基于x_label为同系列数据设置不同颜色

解决Pygal单系列柱子按x_label设置不同颜色的问题

你遇到的问题确实是Pygal默认行为带来的小局限:它默认按系列分配颜色,单系列的所有柱子会共享同一种颜色;拆分多个系列又会破坏x_label的正常显示。不过我们可以利用Pygal Style的动态颜色回调函数来完美解决这个需求,不需要拆分系列,同时保留x_label和自定义颜色。

核心思路

Pygal的Style类允许color参数是一个回调函数,这个函数会接收当前数据点的系列、索引、值和配置信息,我们可以根据数据点在系列中的索引(对应x_label的位置)来返回对应的颜色,这样就能给工作日和周末的柱子设置不同颜色了。

修正后的代码

基于你第二个方案的代码修改,只需要调整style_config中的color设置:

import pygal
from pygal.style import Style

y_values = [12.85, 12.78, 13.74, 16.73, 12.52, 3.71, 1.96]
x_labels = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
filename = 'barchar_test.png'

chart_config = {
    "human_readable": True,
    "pretty_print": True,
    "truncate_legend": -1,
    "value_font_size": 15,
    "print_values": True,
    "show_legend": False,
    "print_values_position": "top",
    "print_labels": True,
    "value_formatter": lambda x: "{0: .2f}".format(x),
}

# 修改style_config,用回调函数动态设置颜色
style_config = {
    "font_family": "googlefont:lato",
    "plot_background": "white",
    "value_font_size": 15,
    "show_y_guides": False,
    "show_y_labels": False,
    # 用lambda函数根据索引返回颜色:前5个是工作日,后2个是周末
    "color": lambda series, index, value, config: "#0099d6" if index < 5 else "#6d6f71"
}

def _plot_bar_chart(y_values, x_labels, filename):
    bar_chart = pygal.Bar(style=Style(**style_config), **chart_config)
    bar_chart.x_labels = x_labels
    # 依然用单个系列,所有数据放在一起
    bar_chart.add('', y_values)
    bar_chart.render_to_png(filename)

_plot_bar_chart(y_values, x_labels, filename)

为什么这个方法有效?

  • 我们保留了单系列的设置,所以x_label可以正常显示,每个柱子对应正确的日期。
  • color回调函数会为系列中的每个数据点(也就是每个柱子)单独计算颜色:索引0-4对应周一到周五,返回蓝色#0099d6;索引5-6对应周六周日,返回灰色#6d6f71。
  • 完全符合你的需求:区分工作日和周末的颜色,同时保留x_label和柱子的正确布局。

其他可选方案(不推荐,供参考)

如果你不想用回调函数,也可以把每个柱子做成单独的系列,但需要让每个系列的点落在对应的x位置上:

def _plot_bar_chart(y_values, x_labels, filename):
    bar_chart = pygal.Bar(style=Style(**style_config), **chart_config)
    bar_chart.x_labels = x_labels
    colors = ["#0099d6"]*5 + ["#6d6f71"]*2
    for i, item in enumerate(y_values):
        # 构造一个列表,只有对应索引的位置有值,其余为None
        data = [None]*i + [item] + [None]*(len(x_labels)-i-1)
        bar_chart.add('', data, color=colors[i])
    bar_chart.render_to_png(filename)

不过这种方法需要构造大量的None值,代码冗余且可读性差,不如回调函数的方法简洁。

内容的提问来源于stack exchange,提问作者Nadros

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 17:47:35