특정 속성을 기반으로 다양한 제품을 표시하는 플롯을 작성 중입니다. Bokeh의 "영화"예제에서 그래프의 디자인을 모델링했습니다. 원본 폴더로 이동하여 "bokeh serve --show shafts" from Andaconda Prompt
을 실행하여 내 플롯을 실행할 수 있습니다.Bokeh 데이터베이스 플로팅 및 업데이트
내 문제는 첨부 파일없이 여러 사람에게 배포 할 수 있도록 HTML 파일을 저장해야한다는 것입니다. 내가 저장하려고 경우 HTML은 영화 예제 또는 내 코드 중 하나에서
"output_file("slider.html", title="slider.py example")"
를 제출 한 후 HTML에서 플롯 그래프를 업데이트하지 슬라이더를 파일을 실행합니다. 문제는 그 파일을 "bokeh serve --show shafts" from Andaconda Prompt
에서 실행할 때 서버에서 실행 중이며 계속해서 파이썬 코드에 액세스 할 수 있다고 생각합니다.
또는 HTML에서 실행하면 모든 코드를 JASON 형식으로 컴파일하고 더 이상 파이썬 코드에 액세스 할 수 없습니다. 이 문제를 해결하기 위해 Bokeh는 서버에서 계속 업데이트 될 작은 자바 스크립트 섹션을 추가했습니다.
Bokeh는이 작업을 수행하는 방법에 대한 여러 예제를 제공하지만 Javascript에서 그래프를 업데이트하기 위해 업데이트되는 내용을 완전히 파악하지 못했습니다. JS에 익숙하지 않아 조금 어렵습니다. 그들이주는 간단한 예는 다음과 같습니다
from bokeh.layouts import column
from bokeh.models import CustomJS, ColumnDataSource, Slider
from bokeh.plotting import figure, output_file, show
output_file("callback.html")
x = [j*0.005 for j in range(0, 200)]
y = x
source = ColumnDataSource(data=dict(x=x, y=y))
plot = figure(plot_width=400, plot_height=400)
plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)
callback = CustomJS(args=dict(source=source), code="""
var data = source.data;
var f = cb_obj.value
x = data['x']
y = data['y']
for (i = 0; i < x.length; i++) {
y[i] = Math.pow(x[i], f)
}
source.change.emit();
""")
slider = Slider(start=0.1, end=4, value=1, step=.1, title="power", callback=callback)
layout = column(slider, plot)
show(layout)
y[i]
플롯을 업데이트 업데이트되고 있지만, 원래 파이썬 업데이트 관련 또는 왜 이러한 변화가 그래프에 영향을 줄 수 어떻게 알아낼 수없는 것을 분명히하는 그것의 범위를 벗어난 것으로 보인다. 내 진짜 질문은 내 코드에서, Bokeh 서버에서 코드를 실행하려면 어떤 변수를 업데이트해야합니까?
벨로우는 제 코드입니다. for control in controls: control.on_change('value'.......
은 서버에서 그래프를 업데이트하는 코드 부분이지만 HTML로 저장 될 때 업데이트되도록 JavaScript 코드로 대체해야합니다.
사전
에 너무 많은callback = CustomJS(args=dict(source=source), code="""
var data = source.data;
selected = shafts[
((data.Weight2g >= min_weight_slider.value) &&
(data.Weight2g <= max_weight_slider.value) &&
(data.Butt_Frequency >= min_butt_freq_slider.value) &&
(data.Butt_Frequency <= max_butt_freq_slider.value) &&
(data.Tip_Frequency >= min_tip_freq_slider.value) &&
(data.Tip_Frequency <= max_tip_freq_slider.value) &&
(data.Torque >= min_torque_slider.value) &&
(data.Torque <= max_torque_slider.value))
];
data = selected;
source.data = selected;
}
source.change.emit;
""")
min_weight_slider = Slider(title="Minimum Weight", value=40,
start=40.0, end=200.0, step=0.5, callback = callback)
callback.args["min_weight_slider"] = min_weight_slider
max_weight_slider = Slider(title="Maximum Weight", value=200, start=40.0, end=200.0, step=0.5, callback = callback)
callback.args["max_weight_slider"] = max_weight_slider
min_butt_freq_slider = Slider(title="Minimum Butt Frequency", value=180.0, start=100.0, end=500.0, step=10.0, callback = callback)
callback.args["min_butt_freq_slider"] = min_butt_freq_slider
max_butt_freq_slider = Slider(title="Maximum Butt Frequency", value=500.0, start=100.0, end=500.0, step=10.0, callback = callback)
callback.args["max_butt_freq_slider"] = max_butt_freq_slider
min_tip_freq_slider = Slider(title="Minimum Tip Frequency", value=180, start=100, end=500, step=10, callback = callback)
callback.args["min_tip_freq_slider"] = min_tip_freq_slider
max_tip_freq_slider = Slider(title="Maximum Tip Frequency", value=400, start=100, end=500, step=10, callback = callback)
callback.args["max_tip_freq_slider"] = max_tip_freq_slider
min_torque_slider = Slider(title="Minimum Torque", value=2, start=1, end=20, step=0.1, callback = callback)
callback.args["min_torque_slider"] = min_torque_slider
max_torque_slider = Slider(title="Maximum Torque", value=15, start=1, end=20, step=0.1, callback = callback)
callback.args["max_torque_slider"] = max_torque_slider
x_axis = Select(title="X Axis", options=sorted(axis_map.keys()), value="Butt_Frequency")
callback.args["x_axis"] = x_axis
y_axis = Select(title="Y Axis", options=sorted(axis_map.keys()), value="Tip_Frequency")
callback.args["y_axis"] = y_axis
def select_shafts():
selected = shafts[
(shafts.Weight2g >= min_weight_slider.value) &
(shafts.Weight2g <= max_weight_slider.value) &
(shafts.Butt_Frequency >= min_butt_freq_slider.value) &
(shafts.Butt_Frequency <= max_butt_freq_slider.value) &
(shafts.Tip_Frequency >= min_tip_freq_slider.value) &
(shafts.Tip_Frequency <= max_tip_freq_slider.value) &
(shafts.Torque >= min_torque_slider.value) &
(shafts.Torque <= max_torque_slider.value)
]
return selected
#updates the
def update():
df = select_shafts()
#re-names the above function
x_name = axis_map[x_axis.value]
y_name = axis_map[y_axis.value]
p.xaxis.axis_label = x_axis.value
p.yaxis.axis_label = y_axis.value
p.title.text = "%d shafts selected" % len(df)
source.data = dict(
x=df[x_name],
y=df[y_name],
color=df["color"],
Manufacture=df["Manufacture"],
Model = df["Model"],
Type = df["Type"],
Weight = df["Weight"],
Flex=df["Flex"],
Butt_Frequency = df["Butt_Frequency"],
Tip_Frequency = df["Tip_Frequency"],
Torque=df["Torque"],
Weight2G = df["Weight2g"],
Availability = df["Availability"],
alpha=df["alpha"]
)
controls = [min_weight_slider, max_weight_slider, min_butt_freq_slider, max_butt_freq_slider, min_tip_freq_slider, max_tip_freq_slider, min_torque_slider, max_torque_slider,x_axis, y_axis]
#for control in controls:
#control.on_change('value', lambda attr, old, new: update())
sizing_mode = 'fixed' # 'scale_width' also looks nice with this example
inputs = widgetbox(*controls, sizing_mode=sizing_mode)
#Widget box produced with bokeh
l = layout([
[inputs, p]
], sizing_mode=sizing_mode)
update() # initial load of the data
curdoc().add_root(l)
curdoc().title = "Shafts"
show(l)
덕분에 나는 내 문제를 해결하기 위해 내 시도에 업데이 트를 추가하고 싶었다. 프로그램이 Bokeh 서버에서 실행될 때 플롯 기능이 액세스 할 수있는 소스 데이터를 지속적으로 업데이트 할 수 있다는 것을 알고 있습니다. 프로그램이 JS 함수를 실행할 때 개별 사전 항목 키 내부의 값만 업데이트 할 수 있습니다.
나는이 필요를 모방하기 위해 modify이 코드를 시도하고 있습니다.
bokeh 서버를 사용해야합니까, 아니면 자바 스크립트 콜백만으로 할 수 있습니까? – Anthonydouc
@Anthonydouc 궁극적으로 나는 자바 스크립트 콜백을 사용하여 실행하고있다. 두 개의 사전을 콜백에 전달하는 방법을 알아 내야했습니다. 하나는 원래 데이터 세트로 정적이었고 하나는 선택한 기준에 따라 수정 된 것입니다. 나는 출력을 브라우저 콘솔에 출력하는데 많은 시간을 할애했다. –
Ok는 정확한 접근 방법처럼 보이고, 자주 bokeh를 사용하면 낭비되는 시간을 낭비하게됩니다. 필자는 플로팅 등을 위해 사용되는 데이터 소스와는 별도의 데이터 소스에서 원래의 데이터를 자주 유지 보수했습니다. – Anthonydouc