python - bokeh - 具有灵活映射的多线图
问题描述
我有以下格式的 Pandas DataFrame
name - date - score
A - 1/1/10 - 100
A - 1/2/10 - 200
A - 1/3/10 - 300
B - 1/1/10 - 150
B - 1/2/10 - 400
B - 1/3/10 - 600
我想创建一个散景图,在 x 轴上有日期,在 y 轴上有分数,每个名称都有单独的线 + 颜色。我正在使用 Jupyter 笔记本工作。
这是一些测试数据,尽管我想获得适用于名称中任意数量/值的东西,而不仅仅是 A 和 B。
import pandas as pd
import datetime
test_data = {'name':['A','A','A','B','B','B'],
'date':[datetime.date(2010,1,1),
datetime.date(2010,2,1),
datetime.date(2010,3,1),
datetime.date(2010,1,1),
datetime.date(2010,2,1),
datetime.date(2010,3,1),],
'score':[100,200,300,150,400,600]}
plot_df = pd.DataFrame(test_data)
使用 Seaborn,我会这样做。
import seaborn as sns
ax = sns.lineplot(data=plot_df, x='date',y='score',hue='name')
我想知道使用 Bokeh 做同样事情的最有效方法是什么?
我可以像这样绘制单个玩家。
import bokeh.plotting as bp
bp.output_notebook()
filtered_df = plot_df[plot_df.player == 'A'].sort_values(by=['date'])
plot_ds = bp.ColumnDataSource(filtered_df)
plot = bp.figure()
plot.line('date','score',source=plot_ds)
bp.show(plot)
我想知道如何让它适用于任意数量的不同名称。同样,我需要它对不同名称数量的变化具有鲁棒性。
我想我应该以某种方式使用颜色映射器,但对我到底如何合并它感到困惑?我还看到这里有另一个答案,它对变量进行硬编码 --> 颜色映射,并试图想出概括这一点的最简单方法。
编辑 - 多线图还需要每个名称的图例,类似于 Seaborn 示例。
下一步是让它工作,以便您可以使用滑块 + 单选按钮动态更改名称和日期范围,但我想让这个更简单的绘图首先工作。这就是为什么我不只是坚持使用 Seaborn。
解决方案
也许是这样的(对于 Bokeh 1.1.0):
import pandas as pd
import datetime
import bokeh.plotting as bp
from bokeh.palettes import Category10
test_data = {'name': ['A', 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'C'],
'date': [datetime.date(2010, 1, 1),
datetime.date(2010, 2, 1),
datetime.date(2010, 3, 1),
datetime.date(2010, 1, 1),
datetime.date(2010, 2, 1),
datetime.date(2010, 3, 1),
datetime.date(2010, 1, 1),
datetime.date(2010, 2, 1),
datetime.date(2010, 3, 1), ],
'score': [100, 200, 300, 150, 400, 600, 150, 250, 400]}
plot_df = pd.DataFrame(test_data)
gby = plot_df.groupby('name')
names = list(gby.groups.keys())
palette = Category10[len(names)]
plot_df['color'] = [palette[names.index(x)] for i, sdf in gby for x in sdf['name']]
plot = bp.figure(x_axis_type = 'datetime')
gby.apply(lambda d: plot.line('date', 'score', line_color = d['color'].unique()[0], line_width = 3, legend = d['name'].unique()[0], source = d))
bp.show(plot)
或使用multi_line
:
import pandas as pd
import datetime
import bokeh.plotting as bp
from bokeh.palettes import Category10
from bokeh.models import ColumnDataSource
test_data = {'name': ['A', 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'C'],
'date': [datetime.date(2010, 1, 1),
datetime.date(2010, 2, 1),
datetime.date(2010, 3, 1),
datetime.date(2010, 1, 1),
datetime.date(2010, 2, 1),
datetime.date(2010, 3, 1),
datetime.date(2010, 1, 1),
datetime.date(2010, 2, 1),
datetime.date(2010, 3, 1), ],
'score': [100, 200, 300, 150, 400, 600, 150, 250, 400]}
plot_df = pd.DataFrame(test_data)
gby = plot_df.groupby('name')
plot = bp.figure(x_axis_type = 'datetime')
x = [list(sdf['date']) for i, sdf in gby]
y = [list(sdf['score']) for i, sdf in gby]
source = ColumnDataSource(dict( x = x,
y = y,
legend = plot_df['name'].unique(),
color = Category10[len(plot_df['name'].unique())]))
plot.multi_line('x', 'y', legend = 'legend', line_color = 'color', line_width = 3, source = source)
bp.show(plot)
结果(两个选项):
推荐阅读
- c# - IIS - 网站 - 浏览 - 解析错误消息:解析实体名称时出错:第 5 行位置 51
- python - Selenium 很慢,有什么选择吗?
- python-3.x - Elasticsearch - 新近度提升错误:“[提升]中 START_OBJECT 的未知键。”
- reactjs - 如何在 Django Rest Framework 中传递多个数据或查询集?
- javascript - 如何在Angular 12中的另一个数组数据中获取数组
- javascript - 使用 JavaScript 获取 html 元素的外部 html 时。它没有获得背景图像属性
- accessibility - 为什么 Google SkipTo 链接可以与 href 一起使用?
- vue.js - 在“普通”html 页面中将 VueMapbox 添加到 Vue
- sql-server - 无法在 .NET 应用程序中访问 SQL Server docker
- powerbi - 如何对列求和,但排除列中包含特定文本部分的任何内容