在Jupyter Notebook中更新Bokeh Patches图形的正确方法咨询
嘿,我来帮你理清这个问题!首先得明确:Bokeh里的Patches glyph是靠列表的列表来定义每个多边形坐标的(xs是每个多边形的x坐标子列表组成的大列表,ys同理),而更新的关键在于让Bokeh能检测到数据变化——这也是你第一种方法没效果的核心原因。
先拆解常见的错误操作:如果直接修改source.data['xs']里的子列表(比如source.data['xs'][0] = [新坐标]),Bokeh是感知不到变化的,因为data字典里的xs引用本身没改,Bokeh的更新机制是靠检测整个字段或data字典的引用变更触发的。
下面是两种官方推荐的规范更新方式,比你说的“取巧”方法更严谨:
方法1:更新整个ColumnDataSource的data字典
这是最直接的方式,适合需要批量修改多个多边形的场景。你只需要构造一个新的data字典,确保xs和ys的结构和初始数据一致(列表的列表),然后直接赋值给source.data:
# 初始数据源 source = ColumnDataSource(data={ 'xs': [[1,2,2,1], [3,4,4,3]], 'ys': [[1,1,2,2], [1,1,2,2]] }) # 批量更新数据 new_data = { 'xs': [[0,1,1,0], [3,5,5,3]], # 修改两个多边形的x坐标 'ys': [[0,0,1,1], [0,0,2,2]] # 修改两个多边形的y坐标 } source.data = new_data
这种方式会触发Bokeh的自动更新,逻辑清晰且数据结构一目了然。
方法2:使用patch方法精准修改单个/部分多边形
如果你只需要修改某几个多边形的坐标,用patch方法更高效,它可以针对特定的多边形索引进行修改,不用替换整个数据集:
# 修改第一个多边形的xs和ys source.patch({ 'xs': [(0, [0,1,1,0])], # 元组格式:(多边形索引, 新的坐标列表) 'ys': [(0, [0,0,1,1])] }) # 单独修改第二个多边形的ys source.patch({ 'ys': [(1, [0,0,2,2])] })
这里的索引是指多边形在xs/ys列表中的位置(第一个多边形是0,第二个是1),这种方式能最小化数据传输,在交互式应用里性能更好。
关于你说的“取巧”方法
如果你之前是直接给source.data['xs']重新赋值(比如source.data['xs'] = 新的xs列表),其实这也是可行的——因为这改变了data字典里xs字段的引用,Bokeh能检测到这个变化并更新。但这种方式本质上和方法1类似,只是只更新了单个字段,而方法1是更新整个数据集,更规范。
最后再提醒一句:不管用哪种方法,一定要确保你的xs和ys始终是列表的列表结构,每个子列表对应一个完整的多边形坐标,否则Patches会渲染失败。
内容的提问来源于stack exchange,提问作者Ilya

