等轴 Bokeh 图表

20 投票
2 回答
9260 浏览
提问于 2025-04-30 21:01

Bokeh绘图与等轴

我用PythonBokeh创建了一个图表(见代码)。

from bokeh.plotting import *

figure()
hold()
rect([1,3], [1,1], [1,0.5], [1,0.5])
patch([0,0,4,4], [2,0,0,2], line_color="black", fill_color=None)
show()

我该如何像在matplotlib中使用axis('equal')命令那样,让图表的坐标轴保持相等,从而表示正方形(宽度和高度相同的矩形)呢?

http://matplotlib.org/examples/pylab_examples/axis_equal_demo.html

我看到可以通过改变图表的宽度和高度,或者定义坐标轴的范围来解决这个问题,但我觉得应该有更聪明的办法。

注意:我使用的是Python v.2.7.8Bokeh v.0.6.1

暂无标签

2 个回答

4

可惜的是,似乎两年过去了,这个功能还是没有实现。作为一个替代方案,我写了一个函数,可以根据你想要的宽高比,适当地设置图形的 x_rangey_range 属性,以便展示你的数据。只要不使用像框选缩放这样的工具,让用户去改变宽高比,这个方法就能很好地工作。

__all__ = ['set_aspect']

from bokeh.models import Range1d

def set_aspect(fig, x, y, aspect=1, margin=0.1):
    """Set the plot ranges to achieve a given aspect ratio.

    Args:
      fig (bokeh Figure): The figure object to modify.
      x (iterable): The x-coordinates of the displayed data.
      y (iterable): The y-coordinates of the displayed data.
      aspect (float, optional): The desired aspect ratio. Defaults to 1.
        Values larger than 1 mean the plot is squeezed horizontally.
      margin (float, optional): The margin to add for glyphs (as a fraction
        of the total plot range). Defaults to 0.1
    """
    xmin = min(xi for xi in x)
    xmax = max(xi for xi in x)
    ymin = min(yi for yi in y)
    ymax = max(yi for yi in y)
    width = (xmax - xmin)*(1+2*margin)
    if width <= 0:
        width = 1.0
    height = (ymax - ymin)*(1+2*margin)
    if height <= 0:
        height = 1.0
    xcenter = 0.5*(xmax + xmin)
    ycenter = 0.5*(ymax + ymin)
    r = aspect*(fig.plot_width/fig.plot_height)
    if width < r*height:
        width = r*height
    else:
        height = width/r
    fig.x_range = Range1d(xcenter-0.5*width, xcenter+0.5*width)
    fig.y_range = Range1d(ycenter-0.5*height, ycenter+0.5*height)

if __name__ == '__main__':
    from bokeh.plotting import figure, output_file, show

    x = [-1, +1, +1, -1]
    y = [-1, -1, +1, +1]
    output_file("bokeh_aspect.html")
    p = figure(plot_width=400, plot_height=300, tools='pan,wheel_zoom',
               title="Aspect Demo")
    set_aspect(p, x, y, aspect=2)
    p.circle(x, y, size=10)
    show(p)
23

从Bokeh 0.12.7版本开始,这个功能已经实现了。现在,图表可以接受两个新的属性。

match_aspect这个属性,如果设置为真,就会让数据空间的比例和图表的像素空间的比例保持一致。举个例子,用数据单位画出的正方形,在像素单位中也会变成完美的正方形。

p = figure(match_aspect=True)
p.circle([-1, +1, +1, -1], [-1, -1, +1, +1])

Bokeh match aspect = True

aspect_scale这个属性可以让你进一步控制比例,通过在match_aspect所做的比例调整上再加一个倍数。

p = figure(aspect_scale=2)
p.circle([-1, +1, +1, -1], [-1, -1, +1, +1])

Bokeh aspect scale = 2

p = figure(aspect_scale=0.5)
p.circle([-1, +1, +1, -1], [-1, -1, +1, +1])

Bokeh aspect scale = 0.5

撰写回答