Mikal025
Mikal025

Reputation: 1

Django Bokeh Stacked Bar Chart

Adding more details per guidance...

Here's my model:

class Orders(models.Model):
    Order_ID = models.CharField(max_length=50, primary_key=True, auto_created=True)
    Order_Desc = models.CharField(max_length=255)
    Order_Type = models.CharField(max_length=50)
    Order_Received_Date = models.DateTimeField()
    Order_Priority= models.CharField(max_length=10)
    def __str__(self):
        return (self.Order_ID)

In my views, i have the following query:

 selected_year=request.GET.get('year', datetime.datetime.now().year-1)

 Orders_By_Year = Orders.objects.annotate(extract_year=Cast('Order_Received_Date',CharField())).annotate(year=Substr('extract_year', Length('extract_year')-3, 4))

 Orders = Orders_By_Year.filter(year=selected_year).values('Order_Type','Order_Priority').annotate(order_total=Count('Order_Priority')).order_by('Order_Type', 'Order_Priority')

This generated the following queryset based on the selected year:

<QuerySet [
{'Order_Type': 'Phone', 'Order_Priority': 'NA', 'Order_total': 2}, 
{'Order_Type': 'Web', 'Order_Priority': 'High', 'Order_total': 3}, 
{'Order_Type': 'Web', 'Order_Priority': 'Med', 'Order_total': 9}]>

I want to create a stacked bar chart using Bokeh that shows the total number of orders for each order type; each bar will also show the breakdown order priority (see image).

enter image description here

I'm getting an error because the axis categorical factors (Order Type in this case) is not unique. can someone help me with this?

Upvotes: -1

Views: 75

Answers (1)

Bro From Space
Bro From Space

Reputation: 99

The problem is that bokeh expects unique categorical factors on the x-axis, but your initial queryset contained multiple records for the same Order _Type. In order to fix this, you need to first aggregate your data so that each Order_Type has a breakdown of Order_priority values.

from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource
from collections import defaultdict

data = [
    {'Order_Type': 'Phone', 'Order_Priority': 'NA', 'Order_total': 2},
    {'Order_Type': 'Web', 'Order_Priority': 'High', 'Order_total': 3},
    {'Order_Type': 'Web', 'Order_Priority': 'Med', 'Order_total': 9},
]

aggregated_data = defaultdict(lambda: defaultdict(int))
for entry in data:
    order_type = entry['Order_Type']
    order_priority = entry['Order_Priority']
    aggregated_data[order_type][order_priority] += entry['Order_total']

order_types = list(aggregated_data.keys())
order_priorities = sorted({priority for values in aggregated_data.values() for priority in values})

source_data = {'Order_Type': order_types}
for priority in order_priorities:
    source_data[priority] = [aggregated_data[order_type].get(priority, 0) for order_type in order_types]

source = ColumnDataSource(source_data)
p = figure(x_range=order_types, title="Stacked Order Chart")
colors = ["#c9d9d3", "#718dbf", "#e84d60"][:len(order_priorities)]
p.vbar_stack(order_priorities, x='Order_Type', source=source, color=colors, legend_label=order_priorities)
show(p)

Upvotes: -1

Related Questions