簡體   English   中英

Bokeh - 在下拉菜單中更改時無法更新ColumnDataSource

[英]Bokeh - unable to update ColumnDataSource upon change in dropdown menu

從下拉列表中選擇新值時,我遇到了更新基礎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))

圓圈未更新,因為您實際上沒有配置圓圈調用以使用源:

p.circle(x=source_error.data["base"][i], y=sec, color=colors[i])

當您將實際列表/數組作為xy等傳遞時,就像上面所做的那樣,然后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包含 每列的值需要是一維數組或列表,而不是像這里一樣的列表列表(少數“多”字形接受這個,但不是圓形等)。 也就是說,每個圓圈都需要一個單獨的列,而不是每個圓圈都有一個帶有“子列表”的列。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM