从下拉列表中选择新值时,我遇到了更新底层ColumnDataSource的问题。在"update_data“部分中,我正在为我的绘图更改底层ColumnDataSource的值。绘图上的错误条形会更新,但打印的数据不会改变。我简化了下面的代码。你知道如何更新所有的数据,而不仅仅是错误条吗?
from bokeh.layouts import row, column
from bokeh.models import ColumnDataSource
from bokeh.models.widgets import Slider, TextInput
from bokeh.plotting import figure
from bokeh.io import output_file, show
from bokeh.models.widgets import Dropdown
import pandas as pd
import numpy as np
from bokeh.io import output_file, show, curdoc
from bokeh.layouts import row, column, widgetbox
from bokeh.models import (
ColumnDataSource,
HoverTool,
LinearColorMapper,
BasicTicker,
PrintfTickFormatter,
ColorBar,
Legend,
Whisker,
)
from bokeh.models.widgets import PreText, Select, RadioGroup, TextInput
from bokeh.plotting import figure
from bokeh.transform import dodge, factor_cmap
import bokeh.plotting
from bokeh.models import ColumnDataSource, CustomJS
from bokeh.models.widgets import Button
import io
import base64
import random
import statistics as stat
from bokeh.models.tickers import SingleIntervalTicker
from bokeh.plotting import figure, show
def sectionize(df, rows, cols):
rowWise = df.stack()
colWise = df.transpose().stack()
rowData = []
colData = []
for x in rows:
rowData.append(list(rowWise[x]))
for x in range(1, (cols + 1)):
colData.append(list(colWise[x]))
print("sectionize has occured")
return rowData, colData
def getLowerUpper(data):
lower, upper = [], []
for x in data:
if x:
mean = stat.mean(x)
std = stat.stdev(x)
lower.append(mean - std)
upper.append(mean + std)
else:
lower.append(0)
upper.append(0)
return lower, upper
def sectionizePlot(source, source_error, type, base):
print("sectionize plot created with typ: " + type)
colors = []
for x in range(0, len(base)):
colors.append(getRandomColor())
title = type + "-wise Intensity Distribution"
p = figure(plot_width=600, plot_height=300, title=title)
p.add_layout(
Whisker(source=source_error, base="base", upper="upper", lower="lower"))
for i, sec in enumerate(source.data['base']):
p.circle(x=source_error.data["base"][i], y=sec, color=colors[i])
p.xaxis.axis_label = type
p.yaxis.axis_label = "Intensity"
if (type.split()[-1] == "Row"):
print("hit a row")
conv = dict(enumerate(list("nABCDEFGHIJKLMNOP")))
conv.pop(0)
p.xaxis.major_label_overrides = conv
p.xaxis.ticker = SingleIntervalTicker(interval=1)
print("sectionizePlot changed")
return p
def getRandomColor():
colors = ['aqua', 'aquamarine', 'black', 'blue', 'blueviolet', 'brown', 'burlywood', 'cadetblue', 'chartreuse', 'chocolate',
'coral', 'cornflowerblue', 'crimson', 'cyan', 'darkblue', 'darkcyan', 'darkgoldenrod', 'darkgray', 'darkgreen',
'darkgrey', 'darkkhaki', 'darkmagenta', 'darkolivegreen', 'darkorange', 'darkorchid', 'darkred', 'darksalmon',
'darkseagreen', 'darkslateblue', 'darkslategray', 'darkslategrey', 'darkturquoise', 'darkviolet', 'deeppink',
'deepskyblue', 'dimgray', 'dimgrey', 'dodgerblue', 'firebrick', 'forestgreen', 'fuchsia', 'gold', 'goldenrod',
'gray', 'green', 'greenyellow', 'grey', 'hotpink', 'indianred', 'indigo', 'khaki', 'lavender', 'lawngreen', 'lime',
'limegreen', 'magenta', 'maroon', 'mediumaquamarine', 'mediumblue', 'mediumorchid', 'mediumpurple',
'mediumseagreen', 'mediumslateblue', 'mediumspringgreen', 'mediumturquoise', 'mediumvioletred', 'midnightblue',
'navy', 'olive', 'olivedrab', 'orange', 'orangered', 'orchid', 'peachpuff', 'peru', 'pink', 'plum', 'powderblue',
'purple', 'red', 'rosybrown', 'royalblue', 'saddlebrown', 'salmon', 'sandybrown', 'seagreen', 'sienna', 'silver',
'skyblue', 'slateblue', 'slategray', 'slategrey', 'springgreen', 'steelblue', 'tan', 'teal', 'thistle', 'tomato',
'turquoise', 'violet', 'yellow', 'yellowgreen']
return colors[random.randint(0, 101)]
colBase = list(range(1, 3))
colData = [[1,2,3,4,5,6], [7, 8, 9, 10, 11, 12]]
colData_lower, colData_upper = getLowerUpper(colData)
colSectTotSource = ColumnDataSource(data=dict(base=[]))
colSectTotSource_error = ColumnDataSource(data=dict(base=[], lower=[], upper=[]))
colSectTotSource.data = dict(base=colData)
colSectTotSource_error.data = dict(base=colBase, lower=colData_lower, upper=colData_upper)
menu = [("A", "A"), ("B", "B")]
dropdown = Dropdown(label="Dropdown button", button_type="warning", menu=menu)
colPlot = sectionizePlot(colSectTotSource, colSectTotSource_error, "Column", colBase)
def update_data(attrname, old, new):
d = dropdown.value
if(d == "B"):
colData = [[11,12,13,14,15,16], [17,18,19,20,21,22]]
else:
colData = [[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]]
colData_lower, colData_upper = getLowerUpper(colData)
#colSectTotSource = ColumnDataSource(data=dict(base=[]))
colSectTotSource.data = dict(base=colData)
colSectTotSource_error.data = dict(base=colBase, lower=colData_lower, upper=colData_upper)
for w in [dropdown]:
w.on_change('value', update_data)
inputs = column(dropdown)
curdoc().add_root(row(inputs, colPlot, width=800))
发布于 2019-05-23 07:07:04
circle没有更新,因为您实际上没有将circle的调用配置为使用源代码:
p.circle(x=source_error.data["base"][i], y=sec, color=colors[i])
当您将实际的列表/数组作为x
、y
等传递时,就像上面所做的那样,那么Bokeh就会创建一个新的CDS供内部使用。如果你想要一个字形来利用你传入的源,你实际上必须传递它,坐标应该只引用那个源的列名:
my_source = ColumnDataSource(data=dict(foo=[...], bar=[...]))
p.circle(x="foo", y="bar", source=my_source)
此外,CDS中的数据格式不适用于此用法:
{'base': [[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]]}
顾名思义,ColumnDataSource包含列。每列的值需要是一维数组或列表,而不是像这里那样的列表列表(少数“多”-glyphs接受这一点,但不接受循环,等等)。也就是说,你需要为每个圆都有一个单独的列,而不是每个圆都有一个带有“子列表”的列。
https://stackoverflow.com/questions/56265491
复制相似问题