Goutham
Goutham

Reputation: 53

How do I create an interactive plot in python that generates a new plot depending on where i clicked?

I have sales data across stores, for each month and for different categories of products.

Say I have a heatmap of sales quantities across stores and months on either axes.

Now when I click on heatmap at a spot corresponding to a particular store and month, I need a new barplot generated which shows sales quantities of each category in that month and store.

I have done something similar in SAS VA. I believe its called an interaction effect.

I have tried searching documentation of matplotlib and plotly didnt get anything useful yet.

Upvotes: 2

Views: 212

Answers (1)

Tony
Tony

Reputation: 8297

Here is an example how you could do this in Bokeh v1.1.0

from bokeh.plotting import figure, show
from bokeh.models import TapTool, CustomJS, ColumnDataSource, Row, ColorBar, LinearColorMapper, BasicTicker
from bokeh.models.sources import ColumnDataSource
from bokeh.transform import transform
from bokeh.palettes import Viridis256
import random

stores = ["store 1", "store 2", "store 3"]
months = ["january", "fabruary", "march"]
x = ["store 1", "store 2", "store 3", "store 1", "store 2", "store 3", "store 1", "store 2", "store 3"]
y = ["january", "january", "january", "fabruary", "fabruary", "fabruary", "march", "march", "march"]
colors = ["#0B486B", "#79BD9A", "#CFF09E", "#79BD9A", "#0B486B", "#79BD9A", "#CFF09E", "#79BD9A", "#0B486B" ]

p1 = figure(title = "Categorical Heatmap", tools = "tap", toolbar_location = None,
            x_range = stores, y_range = months)
p1.rect(x = x, y = y, color = colors, width = 1, height = 1)

categories = ['shoes', 'pants', 'suits']
category_sales = {}
for store in stores:
    category_sales[store] = {}
    for month in months:
        category_sales[store][month] = [random.choice([i for i in range(10000)]) for r in range(3)]

dummy_category_sales = [1000, 1100, 1200]
data = {'x': categories, 'y': dummy_category_sales}
source = ColumnDataSource(data)

p2 = figure(x_range = categories)
bars = p2.vbar(x = 'x', top = 'y', source = source, bottom = 0, width = 0.5)
bars.visible = False

code = '''if (cb_data.source.selected.indices.length > 0){
            bars.visible = true;
            selected_index = cb_data.source.selected.indices[0];    
            store = cb_data.source.data['x'][selected_index]
            month = cb_data.source.data['y'][selected_index]

            bars.data_source.data['y'] = category_sales[store][month]
            bars.data_source.change.emit(); 
        }'''

p1.select_one(TapTool).callback = CustomJS(args = dict(bars = bars, category_sales = category_sales), code = code)

plots = Row(p1, p2)
show(plots)

Result:

enter image description here

Upvotes: 2

Related Questions