python - 带有 Bokeh 帮助的 CustomJS 回调(不知道任何 JS!)
问题描述
我正在尝试在 Python 上使用 Bokeh 实现交互式 (HTML) 地图,以便可以在我的个人 GitHub 上发布它。我意识到如果我不想使用 Bokeh Server,我就不能在 Python 中使用回调。在我意识到这个问题之前,我在 Python 上编写了回调或更新函数,现在我在 JS 上重写它时遇到了麻烦。
在从滑块上选择的值中分割出 pandas 数据帧后,该函数会更新地图上活动字形的数据源。
def make_data(year=1718, market='dayof', mode='priority_b',
zone='None', sibling='None'):
"""
This functions subsets the ratexs_dfs by year, market, mode and sibling
parameters refer to the following:
year = school year, 1718 or 1819
market = time at which cutoffs were calculated:
any = anyday, this includes waitlisted applicants and such
dayof = these cutoffs were calculated at the day of the lottery
# it should be noted that only the shp_data from SY1718
has shp_data from both dayof and any markets.
any or dayof markets for SY1819 are identical
since the shp_data was obtained before waitlist placements
mode = priority system.
priority = this system is the native method of the yearself.
SY1718 uses the 2 digit priority system,
SY1819 uses the 3 digit priority system.
priority_b = this is the secondary system. For SY1718, priority
and priority_b are identical. However for SY1819,
priority is the 3 digit priority system, while
priority_b is the SY1819 priorities adapted for the
SY1718 priority system.
sibling = school where applicant would get sibling priority
"""
school_ratex = ratexs_df[(ratexs_df['year'] == year)
& (ratexs_df['market'] == market)
& (ratexs_df['prio_mode'] == mode)
& ((ratexs_df['nhood'] == zone)
| (ratexs_df['nhood'] == 'None'))
& ((ratexs_df['sibling'] == sibling)
| (ratexs_df['sibling'] == 'None'))]
school_ratex = school_ratex.drop_duplicates(subset='school', keep='first')
school_ratex['ratex'] = (school_ratex['ratex'] * 100).round(2)
school_ratex['ratex_str'] = school_ratex['ratex'].astype(str) + ' %'
school_ratex = school_ratex.sort_values(by='priority')
return ColumnDataSource(school_ratex)
那么更新的功能是:
def update(attr, old, new):
# make a new def
new_src = make_data(zone=schoolzone_dd.value,
sibling=sibling_dd.value)
# update data on map
psource2.data.update(new_src.data)
哪里sibling_dd
和schoolzone_dd
是滑块:
# define dropdown widgets
# school lists
schools = ['None']
schools.extend(sorted(src['school'].values.tolist(), reverse=False))
sibling_dd = Select(title='Sibling School',
value=schools[0],
options=schools)
# zones lists
zones = ['None']
zones.extend(sorted(shp_source['app_name'].values.tolist(), reverse=False))
zones.insert(1, schools[1])
schoolzone_dd = Select(title='School Zone',
value=zones[0],
options=zones)
有没有一种简单的方法可以在 CustomJS 调用中使用两个并行滑块的值以类似的方式对数据帧进行切片?
提前致谢。
解决方案
显然,有一种更简单的方法(使用 Python)使用 PScript 编译 Python int Javascript 的包。
解决方案是在没有任何特殊参数的情况下调用小部件,即:
# school lists
schools = ['None']
schools.extend(sorted(source['school'].values.tolist(), reverse=False))
sibling_dd = Select(title='Sibling School',
value=schools[1],
options=schools)
定义你的回调:
def callback(source=source_bok, original_source=original_source,
sibling_source=sibling_dd, zone_source=schoolzone_dd):
# initialize data
data = original_source.data
s_data = source.data
zone = zone_source.value
sibling = sibling_source.value
# fetch unique schools
schools = s_data['school']
# fetch columns from original data
orig_schools = data['school']
orig_nhoods = data['nhood']
orig_sibling = data['sibling']
orig_year = data['year']
orig_market = data['market']
orig_prio_mode = data['prio_mode']
orig_ratex = original_source.data['ratex']
orig_ratex_str = data['ratex_str']
orig_priority = data['priority']
no_prio_ratex = []
no_prio_ratex_str = []
no_prio_priority = []
for row in range(len(orig_schools)):
for j in range(len(schools)):
if ((orig_nhoods[row] == 'None')
& (orig_sibling[row] == 'None')
& (orig_schools[row] == schools[j])
& (orig_year[row] == 1718)
& (orig_market[row] == 'dayof')
& (orig_prio_mode[row] == 'priority_b')):
no_prio_ratex.append(orig_ratex[row])
no_prio_ratex_str.append(orig_ratex_str[row])
no_prio_priority.append(orig_priority[row])
#return (no_prio_ratex, no_prio_ratex_str, no_prio_priority)
if (zone == 'None') & (sibling == 'None'):
s_data['ratex_str'] = no_prio_ratex_str
s_data['ratex'] = no_prio_ratex
s_data['priority'] = no_prio_priority
if (zone == 'None') & (sibling != 'None'):
s_prio_ratex = []
s_prio_ratex_str = []
s_prio_priority = []
for row in range(len(orig_schools)):
for j in range(len(schools)):
if ((orig_nhoods[row] == 'None')
& (orig_sibling[row] == sibling)
& (orig_schools[row] == schools[j])
& (orig_year[row] == 1718)
& (orig_market[row] == 'dayof')
& (orig_prio_mode[row] == 'priority_b')):
s_prio_ratex.append(orig_ratex[row])
s_prio_ratex_str.append(orig_ratex_str[row])
s_prio_priority.append(orig_priority[row])
s_data['ratex'] = [s_prio_ratex[0] if s_data['school'][i] == sibling else s_data['ratex'][i] for i in range(len(s_data['school']))]
s_data['ratex_str'] = [s_prio_ratex_str[0] if s_data['school'][i] == sibling else s_data['ratex_str'][i] for i in range(len(s_data['school']))]
s_data['priority'] = [s_prio_priority[0] if s_data['school'][i] == sibling else s_data['priority'][i] for i in range(len(s_data['school']))]
if (zone != 'None') & (sibling == 'None'):
n_prio_ratex = []
n_prio_ratex_str = []
n_prio_priority = []
for row in range(len(orig_schools)):
for j in range(len(schools)):
if ((orig_nhoods[row] == zone)
& (orig_sibling[row] == 'None')
& (orig_schools[row] == schools[j])
& (orig_year[row] == 1718)
& (orig_market[row] == 'dayof')
& (orig_prio_mode[row] == 'priority_b')):
n_prio_ratex.append(orig_ratex[row])
n_prio_ratex_str.append(orig_ratex_str[row])
n_prio_priority.append(orig_priority[row])
s_data['ratex'] = [n_prio_ratex[0] if s_data['school'][i] == zone else s_data['ratex'][i] for i in range(len(s_data['school']))]
s_data['ratex_str'] = [n_prio_ratex_str[0] if s_data['school'][i] == zone else s_data['ratex_str'][i] for i in range(len(s_data['school']))]
s_data['priority'] = [n_prio_priority[0] if s_data['school'][i] == zone else s_data['priority'][i] for i in range(len(s_data['school']))]
if (zone != 'None') & (sibling != 'None'):
ns_prio_ratex = []
ns_prio_ratex_str = []
ns_prio_priority = []
for row in range(len(orig_schools)):
for j in range(len(schools)):
if ((orig_nhoods[row] == zone)
& (orig_sibling[row] == sibling)
& (orig_schools[row] == schools[j])
& (orig_year[row] == 1718)
& (orig_market[row] == 'dayof')
& (orig_prio_mode[row] == 'priority_b')):
ns_prio_ratex.append(orig_ratex[row])
ns_prio_ratex_str.append(orig_ratex_str[row])
ns_prio_priority.append(orig_priority[row])
s_data['ratex'] = [ns_prio_ratex[0] if (s_data['school'][i] == zone) & (s_data['school'][i] == sibling) else s_data['ratex'][i] for i in range(len(s_data['school']))]
s_data['ratex_str'] = [ns_prio_ratex_str[0] if (s_data['school'][i] == zone) & (s_data['school'][i] == sibling) else s_data['ratex_str'][i] for i in range(len(s_data['school']))]
s_data['priority'] = [ns_prio_priority[0] if (s_data['school'][i] == zone) & (s_data['school'][i] == sibling) else s_data['priority'][i] for i in range(len(s_data['school']))]
if zone == 'None':
s_data['nhood'] = ['None' for school in s_data['school']]
else:
s_data['nhood'] = [zone if school == zone else 'None' for school in s_data['school']]
if sibling == 'None':
s_data['sibling'] = ['None' for school in s_data['school']]
else:
s_data['sibling'] = [sibling if school == sibling else 'None' for school in s_data['school']]
source.change.emit()def callback(source=source_bok, original_source=original_source,
sibling_source=sibling_dd, zone_source=schoolzone_dd):
# initialize data
data = original_source.data
s_data = source.data
zone = zone_source.value
sibling = sibling_source.value
# fetch unique schools
schools = s_data['school']
# fetch columns from original data
orig_schools = data['school']
orig_nhoods = data['nhood']
orig_sibling = data['sibling']
orig_year = data['year']
orig_market = data['market']
orig_prio_mode = data['prio_mode']
orig_ratex = original_source.data['ratex']
orig_ratex_str = data['ratex_str']
orig_priority = data['priority']
no_prio_ratex = []
no_prio_ratex_str = []
no_prio_priority = []
for row in range(len(orig_schools)):
for j in range(len(schools)):
if ((orig_nhoods[row] == 'None')
& (orig_sibling[row] == 'None')
& (orig_schools[row] == schools[j])
& (orig_year[row] == 1718)
& (orig_market[row] == 'dayof')
& (orig_prio_mode[row] == 'priority_b')):
no_prio_ratex.append(orig_ratex[row])
no_prio_ratex_str.append(orig_ratex_str[row])
no_prio_priority.append(orig_priority[row])
#return (no_prio_ratex, no_prio_ratex_str, no_prio_priority)
if (zone == 'None') & (sibling == 'None'):
s_data['ratex_str'] = no_prio_ratex_str
s_data['ratex'] = no_prio_ratex
s_data['priority'] = no_prio_priority
if (zone == 'None') & (sibling != 'None'):
s_prio_ratex = []
s_prio_ratex_str = []
s_prio_priority = []
for row in range(len(orig_schools)):
for j in range(len(schools)):
if ((orig_nhoods[row] == 'None')
& (orig_sibling[row] == sibling)
& (orig_schools[row] == schools[j])
& (orig_year[row] == 1718)
& (orig_market[row] == 'dayof')
& (orig_prio_mode[row] == 'priority_b')):
s_prio_ratex.append(orig_ratex[row])
s_prio_ratex_str.append(orig_ratex_str[row])
s_prio_priority.append(orig_priority[row])
s_data['ratex'] = [s_prio_ratex[0] if s_data['school'][i] == sibling else s_data['ratex'][i] for i in range(len(s_data['school']))]
s_data['ratex_str'] = [s_prio_ratex_str[0] if s_data['school'][i] == sibling else s_data['ratex_str'][i] for i in range(len(s_data['school']))]
s_data['priority'] = [s_prio_priority[0] if s_data['school'][i] == sibling else s_data['priority'][i] for i in range(len(s_data['school']))]
if (zone != 'None') & (sibling == 'None'):
n_prio_ratex = []
n_prio_ratex_str = []
n_prio_priority = []
for row in range(len(orig_schools)):
for j in range(len(schools)):
if ((orig_nhoods[row] == zone)
& (orig_sibling[row] == 'None')
& (orig_schools[row] == schools[j])
& (orig_year[row] == 1718)
& (orig_market[row] == 'dayof')
& (orig_prio_mode[row] == 'priority_b')):
n_prio_ratex.append(orig_ratex[row])
n_prio_ratex_str.append(orig_ratex_str[row])
n_prio_priority.append(orig_priority[row])
s_data['ratex'] = [n_prio_ratex[0] if s_data['school'][i] == zone else s_data['ratex'][i] for i in range(len(s_data['school']))]
s_data['ratex_str'] = [n_prio_ratex_str[0] if s_data['school'][i] == zone else s_data['ratex_str'][i] for i in range(len(s_data['school']))]
s_data['priority'] = [n_prio_priority[0] if s_data['school'][i] == zone else s_data['priority'][i] for i in range(len(s_data['school']))]
if (zone != 'None') & (sibling != 'None'):
ns_prio_ratex = []
ns_prio_ratex_str = []
ns_prio_priority = []
for row in range(len(orig_schools)):
for j in range(len(schools)):
if ((orig_nhoods[row] == zone)
& (orig_sibling[row] == sibling)
& (orig_schools[row] == schools[j])
& (orig_year[row] == 1718)
& (orig_market[row] == 'dayof')
& (orig_prio_mode[row] == 'priority_b')):
ns_prio_ratex.append(orig_ratex[row])
ns_prio_ratex_str.append(orig_ratex_str[row])
ns_prio_priority.append(orig_priority[row])
s_data['ratex'] = [ns_prio_ratex[0] if (s_data['school'][i] == zone) & (s_data['school'][i] == sibling) else s_data['ratex'][i] for i in range(len(s_data['school']))]
s_data['ratex_str'] = [ns_prio_ratex_str[0] if (s_data['school'][i] == zone) & (s_data['school'][i] == sibling) else s_data['ratex_str'][i] for i in range(len(s_data['school']))]
s_data['priority'] = [ns_prio_priority[0] if (s_data['school'][i] == zone) & (s_data['school'][i] == sibling) else s_data['priority'][i] for i in range(len(s_data['school']))]
if zone == 'None':
s_data['nhood'] = ['None' for school in s_data['school']]
else:
s_data['nhood'] = [zone if school == zone else 'None' for school in s_data['school']]
if sibling == 'None':
s_data['sibling'] = ['None' for school in s_data['school']]
else:
s_data['sibling'] = [sibling if school == sibling else 'None' for school in s_data['school']]
source.change.emit()
source.change.emit()
作为一个关键部分(我没有真正深入研究文档是不好的)
最后,在保存或渲染之前,调用:
sibling_dd.callback = CustomJS.from_py_func(callback)
确保回调中的所有 python 都符合PScript!
PS - @Matt回答和后续解决方案非常有帮助。
推荐阅读
- javascript - 如何使用选择的语言来显示特定的 pdf 文件
- windows - 在 Windows 上卸载 PostgreSQL
- javascript - 特定的 vue mixin 函数没有被执行
- python - django模板循环遍历从xml响应创建的dict的问题
- python - 如何在 Python 中的二维数组中输入随机生成的整数值
- pusher - 有没有办法通过 API 调用创建 Pusher App?
- vim - 使用 :g 搜索不使用 PyCharm IdeaVIM 插件
- c++ - 这是什么构造:模板
无效函数名称(int i)? - python - 如何找到图像的填充大小?
- vue.js - Vue3在单个文件组件中的元素上存在css类在添加到dom时导致渲染失败,无效的VNode类型:Symbol()