散景链接/基于列而不是行索引/索引的笔刷 [英] Bokeh linking/ brushing based on column instead of row indices / index

查看:46
本文介绍了散景链接/基于列而不是行索引/索引的笔刷的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有与此类似的Pandas DataFrame:

I have Pandas DataFrame that is similar to this:

   person activities  hours  foodeaten
0       1          a      3         12
1       1          b      4         14
2       1          c      6         34
3       2          a      2         45
4       2          b      7         67
5       3          a      5          5
6       3          b      3         -1
7       3          c      2          3
8       3          d     12          5

我想按一个活动绘制一个人在一项活动上花费的时间. 因此,绘制图1:活动a,其中活动a的x =人y =小时 图2:活动b,其中x =人y =活动b的小时数 等

I would like to plot the hours spent by a person on a activity, per activity. so, plot 1: activity a, with x=persons y=hours for activity a plot 2: activity b, with x=persons y=hours for activity b etc.

我想根据人物而不是索引来链接地块.因此,当我为情节1中的人1选择一个圆圈时,出于我的目的,该人在其他情节中的工作时间也应突出显示.

I want to link the plots based on persons, not on index. So when I select the circle for person 1 in plot 1, this person's hours in the other plots should highlight, for my purpose as well.

MWE:

from bokeh.io import output_notebook, show, output_file, reset_output
from bokeh.plotting import figure
from bokeh.layouts import gridplot
from bokeh.models import ColumnDataSource, CDSView, BooleanFilter
import pandas as pd

# data
data = {'person':[1,1,1,2,2,3,3,3,3],'activities':['a','b','c','a','b','a','b','c','d'], 'hours':[3,4,6,2,7,5,3,2,12],
       'foodeaten':[12,14,34,45,67,5,-1,3,5]}
df = pd.DataFrame(data=data)
source = ColumnDataSource(data=df)

# filtering the data on activity
v1 = df.activities=='a'
v2 = df.activities=='b'
v3 = df.activities=='c'
v4 = df.activities=='d'

# creating a view to filter the source data on activity
view1 = CDSView(source=source, filters=[BooleanFilter(v1.values.tolist())])
view2 = CDSView(source=source, filters=[BooleanFilter(v2.values.tolist())])
view3 = CDSView(source=source, filters=[BooleanFilter(v3.values.tolist())])
view4 = CDSView(source=source, filters=[BooleanFilter(v4.values.tolist())])

# Plot options
tools       = 'pan,box_select,lasso_select,help,poly_select,hover,wheel_zoom,reset'
plot_width  = 300
plot_height = 300
TOOLTIPS    = [("Person", "@person"),
               ("hours",  "@hours"),]
plot_options = dict(plot_width=plot_width, plot_height=plot_height, tools =tools, tooltips= TOOLTIPS)

# plotting
p1 = figure(title ='activity a',**plot_options)
p1.circle('person', y='hours', size=15, view=view1, source=source)
plot_options['x_range']= p1.x_range

p2 = figure(title ='activity b',**plot_options)
p2.circle('person', y='hours', size=15, view=view2, source=source)

p3 = figure(title ='activity c',**plot_options)
p3.circle('person', y='hours', size=15, view=view3, source=source)

p4 = figure(title ='activity d',**plot_options)
p4.circle('person', y='hours', size=15, view=view4, source=source)

p12 = figure(title ='activity a',**plot_options)
p12.circle('person', y='foodeaten', size=15, view=view1, source=source)
plot_options['x_range']= p1.x_range

p22 = figure(title ='activity b',**plot_options)
p22.circle('person', y='foodeaten', size=15, view=view2, source=source)

p32 = figure(title ='activity c',**plot_options)
p32.circle('person', y='foodeaten', size=15, view=view3, source=source)

p42 = figure(title ='activity d',**plot_options)
p42.circle('person', y='foodeaten', size=15, view=view4, source=source)

p = gridplot([[p1,p12],[p2,p22],[p3,p32],[p4,p42]])
output_file('test.html')
show(p)

此示例按行显示了链接行为,但我想通过在图形中选择此人的属性来突出显示该人的所有内容.

This example shows the linking behaviour, row wise, but I would like to highlight everything for a person by selecting an attribute of this person in a graph.

推荐答案

以下是任意数量绘图的有效示例:

Here is a working example for arbitrary number of plots:

from bokeh.plotting import figure, show
from bokeh.layouts import gridplot
from bokeh.models import ColumnDataSource, CDSView, BooleanFilter, CustomJS
import pandas as pd

data = {'person': [1, 1, 1, 2, 2, 3, 3, 3, 3], 'activities':['a', 'b', 'c', 'a', 'b', 'a', 'b', 'c', 'd'], 'hours':[3, 4, 6, 2, 7, 5, 3, 2, 12], 'foodeaten':[12, 14, 34, 45, 67, 5, -1, 3, 5]}
df = pd.DataFrame(data = data)
source = ColumnDataSource(data = df)
views = [(df.activities == l) for l in ['a', 'b', 'c', 'd']]
filtered_views = [CDSView(source = source, filters = [BooleanFilter(view.values.tolist())]) for view in views]
plot_options = dict(plot_width = 250, plot_height = 250, tools = "tap,pan,wheel_zoom,reset,save", tooltips = [("Person", "@person"), ("hours", "@hours")])
plots = [figure(title = 'activity {l}'.format(l = l), **plot_options) for l in ['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd']]
[plot.circle('person', y = name, size = 15, view = view, source = source) for plot, view, name in zip(plots, 2 * filtered_views, 4 * ['hours'] + 4 * ['foodeaten'])]
callback = CustomJS(args = dict(source = source, plots = plots), code = """
const selected_index = source.selected.indices[0]
const person = source.data['person'][selected_index]
var all_selected = [];
for (index in source.data['index']){
    if (source.data['person'][index] == person)
    all_selected.push(index) 
}
source.selected.indices = all_selected; """)

[plot.js_on_event('tap', callback) for plot in plots]
show(gridplot(children = [plot for plot in plots], ncols = 2))

这篇关于散景链接/基于列而不是行索引/索引的笔刷的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆