在Jupyter中用Bokeh实现支持任意名称的多线折线图
使用Bokeh绘制多名称折线图的高效通用方案(适配任意数量name)
你想要的是一个能自动适配任意数量name值、带图例且支持后续动态交互的Bokeh折线图方案,其实用Bokeh的颜色映射工具配合Pandas分组就能轻松实现,完全不用硬编码颜色映射。下面是完整的可运行代码,我会一步步解释关键部分:
完整实现代码
import pandas as pd import datetime from bokeh.plotting import figure, show, output_notebook from bokeh.models import ColumnDataSource, Legend, factor_cmap from bokeh.palettes import Category10 # 可按需更换其他调色板 # 测试数据准备 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) # Jupyter Notebook输出设置 output_notebook() # 1. 获取唯一name列表,准备自动颜色映射 unique_names = plot_df['name'].unique().tolist() # 用Category10调色板自动匹配name数量(超过10个可换Category20) color_map = factor_cmap('name', palette=Category10[len(unique_names)], factors=unique_names) # 2. 创建绘图对象,设置X轴为日期类型 p = figure(x_axis_type='datetime', title='Score Trend by Name', x_axis_label='Date', y_axis_label='Score') # 3. 按name分组绘制折线,同步收集图例项 legend_items = [] for name, group in plot_df.groupby('name'): # 为每个分组创建独立数据源 source = ColumnDataSource(group) # 绘制折线,通过颜色映射自动分配对应颜色 line = p.line('date', 'score', source=source, line_width=2, color=color_map) # 收集当前name对应的图例条目 legend_items.append((name, [line])) # 4. 添加图例到图表 legend = Legend(items=legend_items, location='top_left') p.add_layout(legend) # 5. 显示图表 show(p)
关键细节解释
- 自动颜色映射:
factor_cmap会根据name的唯一值自动从调色板中分配颜色,彻底告别手动写{'A':'red', 'B':'blue'}这类硬编码映射。如果你的name数量超过10个,只需把Category10换成Category20或其他Bokeh内置调色板即可。 - 通用分组遍历:通过
plot_df.groupby('name')遍历所有分组,不管有多少个name值,代码都能自动生成对应折线,完美适配数量变化的场景。 - 图例集成:通过收集每个折线的图例项再统一添加,实现和Seaborn一致的清晰图例效果。
- 动态交互兼容性:这种方式生成的折线都对应独立数据源,后续要加滑块、单选按钮等交互组件时,可直接通过修改数据源或控制折线可见性实现,灵活性拉满。
扩展提示
如果后续要做动态筛选(比如按日期范围或选择特定name),可以把所有数据整合到一个ColumnDataSource中,再用CustomJS或Bokeh Server实现数据过滤,当前的分组方式已经为后续交互打下了扎实基础。
内容的提问来源于stack exchange,提问作者oli5679
相关产品推荐
相关产品推荐

