散景日期时间轴,小刻度的控制
Bokeh datetime axis, control of minor ticks
我有一个提供散景图的网络应用程序(使用散景 v0.12.7)。 x 轴是日期时间,显示用户定义的天数(日期范围默认为 31 天)。在没有在 Bokeh 中定义任何刻度参数的情况下,主要刻度的数量默认为 5,如此处的实时网络应用所示:
https://btac-web-plots.herokuapp.com/avyview?style=snowpacktracker
我想在主要报价之间的每一天显示次要报价。我尝试了以下方法,它允许任何日期范围长度,并每 5 天指定一个主要刻度(start
和 end
是 Pandas 日期时间索引):
num_days = ((end - start) / np.timedelta64(1, 'D')).astype(int)
fig.xaxis.ticker = DaysTicker(
days = np.arange(1, num_days, 5),
num_minor_ticks = 4
)
每 5 天正确显示一次主要报价,但不显示次要报价。另一个可能的解决方案可能是每天绘制主要刻度线,然后将刻度线标签设置为不可见几天,除了每 5 天一次(不确定如何实现这个...)。
在这些图上显示每日次要报价的最佳方法是什么?
这是我的一段绘图代码(包括DaysTicker
),以第一个面板为例:
fig = figure(
title="New Snow, SWE, Snow Depth, and Settlement",
name="newsnow_extra_fig",
x_axis_type="datetime",
y_axis_label='HN24 / SWE (in)',
width=width, height=height2,
tools=tools,
toolbar_sticky=False,
logo=None
)
fig.y_range = Range1d(-12, 30)
fig.extra_y_ranges = {"Depth": Range1d(start=-72, end=180)}
fig.add_layout(LinearAxis(y_range_name="Depth", axis_label='HS (in)' ), 'right')
fig.yaxis.axis_label_standoff = 5
num_days = ((end - start) / np.timedelta64(1, 'D')).astype(int)
fig.xaxis.ticker = DaysTicker(
days=np.arange(1,num_days,5),
num_minor_ticks=4
)
newcds, newcds_sums = create_newsnow_extra_cds(df, 'mid', start, end)
dline = fig.line(source=newcds,
x='Date', y='depth',
line_color="blue", line_width=2, line_alpha=0.5,
legend="snow depth (HS)", name="depthline",
y_range_name='Depth',
)
nsbars = fig.vbar(source=newcds,
x='newsnow_x', width=WIDTH, bottom=0, top='newsnow',
color="blue", alpha=0.9, legend='new snow (HN24)', name='nsbars'
)
swebars = fig.vbar(source=newcds,
x='swex10_x', width=WIDTH, bottom=0, top='swex10',
color="blue", alpha=0.3, legend='SWE x 10', name='swebars'
)
settlebars = fig.vbar(source=newcds,
x='Date', width=WIDTH*2.0, bottom='settle', top=0,
color="orange", alpha=0.75,
name="settlebars", legend="settlement"
)
内置 DatetimeAxis
并没有真正公开与您的用例相对应的次要刻度配置。所以你的选择是:
创建一个 custom extension 到 return 正是您想要的主要和次要刻度
每天使用 "day" 代码并按照您的建议隐藏您不想看到的报价。
第二条路径(您的想法)可能是最容易上手的。这是一个完整的代码示例,它使用 FuncTickFormatter
生成 "blank" 个刻度标签,每五天除外:
import numpy as np
import pandas as pd
from bokeh.io import output_file, show
from bokeh.models import DaysTicker, FuncTickFormatter
from bokeh.plotting import figure
x = pd.date_range("2017-12-01", "2017-12-31")
y = ([1,3,4]*11)[:31]
p = figure(plot_width=800, x_range=(x[0], x[-1]), x_axis_type="datetime")
p.line(x, y, line_dash="4 4", line_width=1, color='gray')
p.xaxis.ticker = DaysTicker(days=np.arange(1,32))
p.xaxis.major_label_orientation = 1.5
p.xaxis.formatter = FuncTickFormatter(code="""
var date = new Date(tick)
var day = date.getUTCDate(date)
if ( day%5 == 0 ) { return day }
else { return "" }
""")
output_file("foo.html")
show(p)
生成此输出
如果你想要的不仅仅是天数,你可以调整 JS 代码中的第一个 if
分支,让 FuncTickFormatter
做的不仅仅是 return day
显然合并了一些功能,可以改善这里的情况,请参阅 How do you add more x axis ticks and labels to datetime axis using Python's Bokeh? and https://github.com/bokeh/bokeh/issues/1668
我有一个提供散景图的网络应用程序(使用散景 v0.12.7)。 x 轴是日期时间,显示用户定义的天数(日期范围默认为 31 天)。在没有在 Bokeh 中定义任何刻度参数的情况下,主要刻度的数量默认为 5,如此处的实时网络应用所示:
https://btac-web-plots.herokuapp.com/avyview?style=snowpacktracker
我想在主要报价之间的每一天显示次要报价。我尝试了以下方法,它允许任何日期范围长度,并每 5 天指定一个主要刻度(start
和 end
是 Pandas 日期时间索引):
num_days = ((end - start) / np.timedelta64(1, 'D')).astype(int)
fig.xaxis.ticker = DaysTicker(
days = np.arange(1, num_days, 5),
num_minor_ticks = 4
)
每 5 天正确显示一次主要报价,但不显示次要报价。另一个可能的解决方案可能是每天绘制主要刻度线,然后将刻度线标签设置为不可见几天,除了每 5 天一次(不确定如何实现这个...)。
在这些图上显示每日次要报价的最佳方法是什么?
这是我的一段绘图代码(包括DaysTicker
),以第一个面板为例:
fig = figure(
title="New Snow, SWE, Snow Depth, and Settlement",
name="newsnow_extra_fig",
x_axis_type="datetime",
y_axis_label='HN24 / SWE (in)',
width=width, height=height2,
tools=tools,
toolbar_sticky=False,
logo=None
)
fig.y_range = Range1d(-12, 30)
fig.extra_y_ranges = {"Depth": Range1d(start=-72, end=180)}
fig.add_layout(LinearAxis(y_range_name="Depth", axis_label='HS (in)' ), 'right')
fig.yaxis.axis_label_standoff = 5
num_days = ((end - start) / np.timedelta64(1, 'D')).astype(int)
fig.xaxis.ticker = DaysTicker(
days=np.arange(1,num_days,5),
num_minor_ticks=4
)
newcds, newcds_sums = create_newsnow_extra_cds(df, 'mid', start, end)
dline = fig.line(source=newcds,
x='Date', y='depth',
line_color="blue", line_width=2, line_alpha=0.5,
legend="snow depth (HS)", name="depthline",
y_range_name='Depth',
)
nsbars = fig.vbar(source=newcds,
x='newsnow_x', width=WIDTH, bottom=0, top='newsnow',
color="blue", alpha=0.9, legend='new snow (HN24)', name='nsbars'
)
swebars = fig.vbar(source=newcds,
x='swex10_x', width=WIDTH, bottom=0, top='swex10',
color="blue", alpha=0.3, legend='SWE x 10', name='swebars'
)
settlebars = fig.vbar(source=newcds,
x='Date', width=WIDTH*2.0, bottom='settle', top=0,
color="orange", alpha=0.75,
name="settlebars", legend="settlement"
)
内置 DatetimeAxis
并没有真正公开与您的用例相对应的次要刻度配置。所以你的选择是:
创建一个 custom extension 到 return 正是您想要的主要和次要刻度
每天使用 "day" 代码并按照您的建议隐藏您不想看到的报价。
第二条路径(您的想法)可能是最容易上手的。这是一个完整的代码示例,它使用 FuncTickFormatter
生成 "blank" 个刻度标签,每五天除外:
import numpy as np
import pandas as pd
from bokeh.io import output_file, show
from bokeh.models import DaysTicker, FuncTickFormatter
from bokeh.plotting import figure
x = pd.date_range("2017-12-01", "2017-12-31")
y = ([1,3,4]*11)[:31]
p = figure(plot_width=800, x_range=(x[0], x[-1]), x_axis_type="datetime")
p.line(x, y, line_dash="4 4", line_width=1, color='gray')
p.xaxis.ticker = DaysTicker(days=np.arange(1,32))
p.xaxis.major_label_orientation = 1.5
p.xaxis.formatter = FuncTickFormatter(code="""
var date = new Date(tick)
var day = date.getUTCDate(date)
if ( day%5 == 0 ) { return day }
else { return "" }
""")
output_file("foo.html")
show(p)
生成此输出
如果你想要的不仅仅是天数,你可以调整 JS 代码中的第一个 if
分支,让 FuncTickFormatter
做的不仅仅是 return day
显然合并了一些功能,可以改善这里的情况,请参阅 How do you add more x axis ticks and labels to datetime axis using Python's Bokeh? and https://github.com/bokeh/bokeh/issues/1668