HINWEIS: Diese Frage betrifft den Bokeh-Server der "ersten Generation", der seit mehreren Jahren nicht mehr verwendet wird. Nichts in dieser Frage und ihre Antworten ist relevant für jede Version von Bokeh> = 0,11Mehrere Fragen mit objektorientiertem Bokeh
Ich versuche Bokeh für eine interaktive App zu verstehen, dass ich baue. Ich schaue auf die Bokeh examples, und ich sehe, dass die meisten Beispiele alle im globalen Namespace geschrieben sind, aber die im Unterverzeichnis "app" sind in einem schönen, objektorientierten Stil geschrieben, wo die Hauptklasse eingibt Eine Property-Klasse wie HBox.
Dies wird ein Mischmasch von Fragen sein, denn ich denke nicht, dass diese Art der Programmierung von Bokeh sehr gut dokumentiert wurde. Das erste, was mir dabei auffiel, war, dass die Handlung nicht gezeichnet wurde, wenn ich nicht extra_generated_classes
einschloss.
Was bedeutet extra_generated_classes tun?
Zweitens sieht es so aus, als ob die Ereignisschleife
setup_events
beim Start vorcreate
aufgerufen wird und anschließend jedes Mal, wenn der Plot ein Ereignis auslöst.Warum müssen setup_events Callbacks jedes Mal registrieren, wenn ein Ereignis ausgelöst wird? Und warum wartet es nicht darauf, dass create beendet wird, bevor es versucht wird, sie beim ersten Mal zu registrieren?
Das letzte, worüber ich mir nicht sicher bin, ist, wie man eine Neuzeichnung einer Glyph hier erzwingt. Das Slider-Demo funktioniert für mich, und ich versuche im Prinzip das Gleiche zu tun, außer mit einem Streudiagramm anstelle einer Linie.
stellte ich eine pdb Spur am Ende meines
update_data
, und ich kann garantieren, dassself.source
self.plot.renderers[-1].data_source
zueinander passen und dass beide von ihnen haben von Anfang an gezwickt worden.self.plot
selbst ändert sich jedoch nicht.Was entspricht der objektorientierte Ansatz dem Aufruf von store_objects, um den Plot zu aktualisieren?
Ich bin besonders verwirrt durch diese dritte, weil es nicht so aussieht wie das sliders_app-Beispiel so etwas braucht.Zur Verdeutlichung, versuche ich, eine variable Anzahl von Widgets/Schieber zu machen, so ist dies, was mein Code wie folgt aussieht:
Klasse Attribute:
extra_generated_classes = [['ScatterBias', 'ScatterBias', 'HBox']]
maxval = 100.0
inputs = Instance(bkw.VBoxForm)
outputs = Instance(bkw.VBoxForm)
plots = Dict(String, Instance(Plot))
source = Instance(ColumnDataSource)
cols = Dict(String, String)
widgets = Dict(String, Instance(bkw.Slider))
# unmodified source
df0 = Instance(ColumnDataSource)
Methode initialize
@classmethod
def create(cls):
obj = cls()
##############################
## load DataFrame
##############################
df = pd.read_csv('data/crime2013_tagged_clean.csv', index_col='full_name')
obj.cols = {'x': 'Robbery',
'y': 'Violent crime total',
'pop': 'Population'
}
cols = obj.cols
# only keep interested values
df2= df.ix[:, cols.values()]
# drop empty rows
df2.dropna(axis=0, inplace=True)
df0 = df2.copy()
df0.reset_index(inplace=True)
# keep copy of original data
obj.source = ColumnDataSource(df2)
obj.df0 = ColumnDataSource(df0)
##############################
## draw scatterplot
##############################
obj.plots = {
'robbery': scatter(x=cols['x'],
y=cols['y'],
source=obj.source,
x_axis_label=cols['x'],
y_axis_label=cols['y']),
'pop': scatter(x=cols['pop'],
y=cols['y'],
source=obj.source,
x_axis_label=cols['pop'],
y_axis_label=cols['y'],
title='%s by %s, Adjusted by by %s'%(cols['y'],
cols['pop'], cols['pop'])),
}
obj.update_data()
##############################
## draw inputs
##############################
# bokeh.plotting.scatter
## TODO: refactor so that any number of control variables are created
# automatically. This involves subsuming c['pop'] into c['ctrls'], which
# would be a dictionary mapping column names to their widget titles
pop_slider = obj.make_widget(bkw.Slider, dict(
start=-obj.maxval,
end=obj.maxval,
value=0,
step=1,
title='Population'),
cols['pop'])
##############################
## make layout
##############################
obj.inputs = bkw.VBoxForm(
children=[pop_slider]
)
obj.outputs = bkw.VBoxForm(
children=[obj.plots['robbery']]
)
obj.children.append(obj.inputs)
obj.children.append(obj.outputs)
return obj
update_data
def update_data(self):
"""Update y by the amount designated by each slider"""
logging.debug('update_data')
c = self.cols
## TODO:: make this check for bad input; especially with text boxes
betas = {
varname: getattr(widget, 'value')/self.maxval
for varname, widget in self.widgets.iteritems()
}
df0 = pd.DataFrame(self.df0.data)
adj_y = []
for ix, row in df0.iterrows():
## perform calculations and generate new y's
adj_y.append(self.debias(row))
self.source.data[c['y']] = adj_y
assert len(adj_y) == len(self.source.data[c['x']])
logging.debug('self.source["y"] now contains debiased data')
import pdb; pdb.set_trace()
Beachten Sie, dass ich sicher bin, dass der Event-Handler ordnungsgemäß eingerichtet und ausgelöst wird. Ich weiß einfach nicht, wie man die geänderten Quelldaten im Streudiagramm wiedergibt.
Haben Sie eine Lösung für dieses Problem gefunden, insbesondere für das Rendern von Streuung? Ich forsche nach Bokeh für etwas Ähnliches. –
Versuchen Sie, Ihre Fragen in kleinere Stücke zu teilen, wenn Sie Antworten wünschen. – sorin