我正在创建一个交互式散点图,其中包括x和y轴的下拉列表。
但是,当前仅当x和y轴源列是数字或日期对象等时才起作用。对于字符串列,则什么都不会显示。
如何更改脚本,使其根据当前下拉菜单自动将轴类型从标称更改为序数,反之亦然?
# -*- coding: utf-8 -*-
from os.path import dirname, join
import numpy as np
import pandas.io.sql as psql
import sqlite3 as sql
import pandas as pd
from bokeh.plotting import figure
from bokeh.layouts import layout, widgetbox
from bokeh.models import ColumnDataSource, Div
from bokeh.models.widgets import Slider, Select, TextInput
from bokeh.io import curdoc
projects = pd.read_excel('explorer_data.xlsx')
#functions
year = lambda x : x.to_pydatetime().year
axis_map = {header:header for header in list(projects)}
# Create Input controls
budget = Slider(title="Minimum budget", value=80, start=0, end=200000, step=1000)
start_date = Slider(title="Project start date", start=1940, end=2019, value=1970, step=1)
end_date = Slider(title="Project end date", start=1940, end=2019, value=2019, step=1)
x_axis = Select(title="X Axis", options=sorted(axis_map.keys()), value="Budget")
y_axis = Select(title="Y Axis", options=sorted(axis_map.keys()), value="Spent/Paid")
# Create Column Data Source that will be used by the plot
source = ColumnDataSource(data=dict(x=[], y=[], number=[], title=[], year=[], revenue=[], alpha=[]))
TOOLTIPS=[
("ID", "@number")
# ("Year", "@year"),
# ("$", "@revenue")
]
p = figure(plot_height=600, plot_width=700, title="", toolbar_location=None, tools = "pan,wheel_zoom,box_zoom,reset", tooltips=TOOLTIPS)
p.circle(x="x", y="y", source=source, size=7)
def select_projects():
selected = projects[
(projects['Budget'] >= budget.value) &
(projects['Start Date'].map(year) >= start_date.value) &
(projects['End Date'].map(year) <= end_date.value)
]
return selected
def update():
df = select_projects()
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 projects selected" % len(df)
source.data = dict(
x=df[x_name],
y=df[y_name],
number=df['Project ID'],
)
controls = [budget, start_date, end_date, 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)
l = layout([
# [desc],
[inputs, p],
], sizing_mode=sizing_mode)
update() # initial load of the data
curdoc().add_root(l)
curdoc().title = "Projects"