Django+Bokeh创建堆叠柱状图时分类轴不唯一的问题求助
解决Bokeh堆叠柱状图分类轴重复的问题
第一步:优化Django数据查询
先把年份提取逻辑换成更高效的TruncYear,避免字符串截取的冗余操作:
from django.db.models.functions import TruncYear import datetime selected_year = request.GET.get('year', datetime.datetime.now().year - 1) # 按年份+订单类型+优先级分组统计数量 orders_data = Orders.objects.annotate( year=TruncYear('Order_Received_Date') ).filter(year__year=selected_year).values( 'Order_Type', 'Order_Priority' ).annotate(order_total=Count('Order_ID')).order_by('Order_Type', 'Order_Priority')
第二步:整理数据为堆叠图所需格式
当前QuerySet是长格式数据(同一订单类型对应多行不同优先级),Bokeh堆叠柱状图需要宽格式数据(每个订单类型唯一,不同优先级作为独立列)。我们先转换数据结构:
# 提取所有唯一的优先级和订单类型 priorities = sorted({item['Order_Priority'] for item in orders_data}) order_types = sorted({item['Order_Type'] for item in orders_data}) # 构建宽格式数据字典 data = {'Order_Type': order_types} for priority in priorities: # 给每个优先级列填充对应订单类型的数量,无数据则补0 data[priority] = [ next((item['order_total'] for item in orders_data if item['Order_Type'] == ot and item['Order_Priority'] == priority), 0) for ot in order_types ]
第三步:用Bokeh绘制堆叠柱状图
使用vbar_stack方法直接生成堆叠效果,此时x轴的订单类型已唯一,不会再报错:
from bokeh.plotting import figure from bokeh.models import ColumnDataSource from bokeh.embed import components # 创建数据源 source = ColumnDataSource(data=data) # 初始化图表 p = figure( x_range=order_types, title=f"{selected_year}年订单类型按优先级堆叠统计", x_axis_label="订单类型", y_axis_label="订单总数", width=800, height=400 ) # 绘制堆叠柱状图 p.vbar_stack( priorities, x='Order_Type', width=0.5, source=source, legend_label=priorities ) # 设置图例 p.legend.title = "订单优先级" p.legend.location = "top_left" # 生成Django模板可用的组件 script, div = components(p)
报错原因说明
你之前的QuerySet中Order_Type存在重复值(比如Web出现两次),直接将这种数据作为Bokeh的x轴数据源时,分类轴会出现重复标签,导致渲染冲突。通过转换为宽格式数据,每个Order_Type仅出现一次,不同优先级的数值作为堆叠系列,就能解决这个问题。
内容的提问来源于stack exchange,提问作者Mikal025
相关产品推荐
相关产品推荐

