使用 Bokeh hbar 和 ColumnDataSource 逐一标记
Labels off-by-one with Bokeh hbar and ColumnDataSource
我有一个由 ColumnDataSource
驱动的 hbar
-plot,y 轴上有分类标签,x 轴上有两个数字。为了在 y 轴上为每个标签设置两组条形图,我构建了两个范围(Things1=df.Thing.index + 1 - 0.2
和 Things2=df.Thing.index + 1 + 0.2
)并将两个 hbar
-实例分别分配给其中一个范围.
当且仅当 ColumnDataSource
中的范围 Things1
和 Things2
以预定义的偏移量 1 构造时,这会给我正确的布局;否则,所有标签和条都恰好偏移一个条目。
我现在构建情节的方式如下所示:
df = pandas.DataFrame([('Store', 'Juice', 3, 19.0),
('Warehouse', 'Paint', 7, 21.0),
('Store', 'Fruit', 2, 6.0),
('Warehouse', 'Grass', 4, 15.0),
('Store', 'Leaves', 9, 32.0)],
columns=('Storage', 'Thing', 'Quantity', 'Valueation'))
source = bokeh.models.ColumnDataSource(dict(Quantity=df.Quantity,
Things1=df.Thing.index + 1 - 0.2, # Why +1 ?
Things2=df.Thing.index + 1 + 0.2, # Why +1 ?
Valueation=df.Valueation,
Storage=df.Storage))
plot = bokeh.plotting.figure(plot_width=800, plot_height=300,
y_range=list(df.Thing.unique()),
x_range=(0, df.Quantity.max() * 1.1))
plot.hbar(y='Things1', right='Quantity', height=0.3, alpha=0.7, source=source)
plot.hbar(y='Things2', right='Valueation', height=0.3, alpha=1, source=source,
x_range_name="ValueationRange")
plot.yaxis.axis_label = 'Thing'
plot.xaxis.axis_label = 'Quantity'
plot.extra_x_ranges = {"ValueationRange":
bokeh.models.Range1d(start=0, end=df.Valueation.max() * 1.1)}
plot.add_layout(bokeh.models.LinearAxis(x_range_name="ValueationRange",
axis_label='Valueation'), 'above')
bokeh.plotting.show(plot)
Things1/2=df.Thing.index + 1 -/+ 0.2
给出正确的情节:
用Things1/2=df.Thing.index -/+ 0.2
我得到
我猜这是因为不同的范围是基于 0 或 1 的。这是一个简单的陷阱还是我做错了?
EDIT 事实证明,原始值(与真正的分类数据相对)与因子范围的这种使用没有记录且未经测试。分类数据的处理将在 0.12.7 中发生变化,这将允许正确使用分类数据所需的功能 - 请参阅下面的 bigreddots(lead bokeh dev)评论。
仅从观察来看,分类范围的默认行为似乎是将整数 y 值从 1 开始映射到类别。
如果在初始化绘图对象后添加 y_range,则会暴露原始刻度:
所以正如你提到的,这只是由于范围。第一个绘制的数据系列从 0 开始,但第一个标签从 1 开始。您可以设置偏移量或使用 funcickformatter 将显式 y 刻度映射到值,这可以精确控制值和标签之间的映射。
如果您查看 http://docs.bokeh.org/en/latest/docs/gallery/categorical.html 等示例,您可以看到数据已映射到类别,但这是因为 y 值本身作为因子输入。在您的示例中,您只是更改了 y 轴,但要抵消您不能使用原始类别本身的值。
顺便说一句:
编辑 0.12.7 中可能不存在偏移属性,因此最好不要依赖它/假设它存在。
查看文档,它说默认偏移量为 0。所以我认为您需要 -1 的偏移量来说明这一点。参见 http://docs.bokeh.org/en/latest/docs/reference/models/ranges.html#bokeh.models.ranges.FactorRange.offset
import pandas
import bokeh
import bokeh.models, bokeh.plotting
df = pandas.DataFrame([('Store', 'Juice', 3, 19.0),
('Warehouse', 'Paint', 7, 21.0),
('Store', 'Fruit', 2, 6.0),
('Warehouse', 'Grass', 4, 15.0),
('Store', 'Leaves', 9, 32.0)],
columns=('Storage', 'Thing', 'Quantity', 'Valueation'))
source = bokeh.models.ColumnDataSource(dict(Quantity=df.Quantity,
Things1=df.Thing.index - 0.2, # Why +1 ?
Things2=df.Thing.index + 0.2, # Why +1 ?
Valueation=df.Valueation,
Storage=df.Storage))
plot = bokeh.plotting.figure(plot_width=800, plot_height=300,
y_range=list(df.Thing.unique()),
x_range=(0, df.Quantity.max() * 1.1))
plot.y_range.offset = -1
plot.hbar(y='Things1', right='Quantity', height=0.3, alpha=0.7, source=source)
plot.hbar(y='Things2', right='Valueation', height=0.3, alpha=1, source=source,
x_range_name="ValueationRange")
plot.yaxis.axis_label = 'Thing'
plot.xaxis.axis_label = 'Quantity'
plot.extra_x_ranges = {"ValueationRange":
bokeh.models.Range1d(start=0, end=df.Valueation.max() * 1.1)}
plot.add_layout(bokeh.models.LinearAxis(x_range_name="ValueationRange",
axis_label='Valueation'), 'above')
bokeh.plotting.show(plot)
我有一个由 ColumnDataSource
驱动的 hbar
-plot,y 轴上有分类标签,x 轴上有两个数字。为了在 y 轴上为每个标签设置两组条形图,我构建了两个范围(Things1=df.Thing.index + 1 - 0.2
和 Things2=df.Thing.index + 1 + 0.2
)并将两个 hbar
-实例分别分配给其中一个范围.
当且仅当 ColumnDataSource
中的范围 Things1
和 Things2
以预定义的偏移量 1 构造时,这会给我正确的布局;否则,所有标签和条都恰好偏移一个条目。
我现在构建情节的方式如下所示:
df = pandas.DataFrame([('Store', 'Juice', 3, 19.0),
('Warehouse', 'Paint', 7, 21.0),
('Store', 'Fruit', 2, 6.0),
('Warehouse', 'Grass', 4, 15.0),
('Store', 'Leaves', 9, 32.0)],
columns=('Storage', 'Thing', 'Quantity', 'Valueation'))
source = bokeh.models.ColumnDataSource(dict(Quantity=df.Quantity,
Things1=df.Thing.index + 1 - 0.2, # Why +1 ?
Things2=df.Thing.index + 1 + 0.2, # Why +1 ?
Valueation=df.Valueation,
Storage=df.Storage))
plot = bokeh.plotting.figure(plot_width=800, plot_height=300,
y_range=list(df.Thing.unique()),
x_range=(0, df.Quantity.max() * 1.1))
plot.hbar(y='Things1', right='Quantity', height=0.3, alpha=0.7, source=source)
plot.hbar(y='Things2', right='Valueation', height=0.3, alpha=1, source=source,
x_range_name="ValueationRange")
plot.yaxis.axis_label = 'Thing'
plot.xaxis.axis_label = 'Quantity'
plot.extra_x_ranges = {"ValueationRange":
bokeh.models.Range1d(start=0, end=df.Valueation.max() * 1.1)}
plot.add_layout(bokeh.models.LinearAxis(x_range_name="ValueationRange",
axis_label='Valueation'), 'above')
bokeh.plotting.show(plot)
Things1/2=df.Thing.index + 1 -/+ 0.2
给出正确的情节:
用Things1/2=df.Thing.index -/+ 0.2
我得到
我猜这是因为不同的范围是基于 0 或 1 的。这是一个简单的陷阱还是我做错了?
EDIT 事实证明,原始值(与真正的分类数据相对)与因子范围的这种使用没有记录且未经测试。分类数据的处理将在 0.12.7 中发生变化,这将允许正确使用分类数据所需的功能 - 请参阅下面的 bigreddots(lead bokeh dev)评论。
仅从观察来看,分类范围的默认行为似乎是将整数 y 值从 1 开始映射到类别。
如果在初始化绘图对象后添加 y_range,则会暴露原始刻度:
所以正如你提到的,这只是由于范围。第一个绘制的数据系列从 0 开始,但第一个标签从 1 开始。您可以设置偏移量或使用 funcickformatter 将显式 y 刻度映射到值,这可以精确控制值和标签之间的映射。
如果您查看 http://docs.bokeh.org/en/latest/docs/gallery/categorical.html 等示例,您可以看到数据已映射到类别,但这是因为 y 值本身作为因子输入。在您的示例中,您只是更改了 y 轴,但要抵消您不能使用原始类别本身的值。
顺便说一句: 编辑 0.12.7 中可能不存在偏移属性,因此最好不要依赖它/假设它存在。
查看文档,它说默认偏移量为 0。所以我认为您需要 -1 的偏移量来说明这一点。参见 http://docs.bokeh.org/en/latest/docs/reference/models/ranges.html#bokeh.models.ranges.FactorRange.offset
import pandas
import bokeh
import bokeh.models, bokeh.plotting
df = pandas.DataFrame([('Store', 'Juice', 3, 19.0),
('Warehouse', 'Paint', 7, 21.0),
('Store', 'Fruit', 2, 6.0),
('Warehouse', 'Grass', 4, 15.0),
('Store', 'Leaves', 9, 32.0)],
columns=('Storage', 'Thing', 'Quantity', 'Valueation'))
source = bokeh.models.ColumnDataSource(dict(Quantity=df.Quantity,
Things1=df.Thing.index - 0.2, # Why +1 ?
Things2=df.Thing.index + 0.2, # Why +1 ?
Valueation=df.Valueation,
Storage=df.Storage))
plot = bokeh.plotting.figure(plot_width=800, plot_height=300,
y_range=list(df.Thing.unique()),
x_range=(0, df.Quantity.max() * 1.1))
plot.y_range.offset = -1
plot.hbar(y='Things1', right='Quantity', height=0.3, alpha=0.7, source=source)
plot.hbar(y='Things2', right='Valueation', height=0.3, alpha=1, source=source,
x_range_name="ValueationRange")
plot.yaxis.axis_label = 'Thing'
plot.xaxis.axis_label = 'Quantity'
plot.extra_x_ranges = {"ValueationRange":
bokeh.models.Range1d(start=0, end=df.Valueation.max() * 1.1)}
plot.add_layout(bokeh.models.LinearAxis(x_range_name="ValueationRange",
axis_label='Valueation'), 'above')
bokeh.plotting.show(plot)