是否有在matplotlib上绘制水平射线的功能?

时间:2018-07-24 23:02:39

标签: python matplotlib

我正在尝试绘制水平射线而不是水平线。 Matplotlib具有axhline()函数。但是它从图表的开头开始绘制。正如您在所附图片中看到的那样,我在条形图的高低处设置点。

有没有办法在特定点上画一条线?

我尝试过fillstyle="right",但我认为这不是我想要的。

Horizontal ray

2 个答案:

答案 0 :(得分:-2)

是的,可以使用plt.axhline绘制水平射线。例如,以下代码生成具有水平射线的箱形图:

import matplotlib.pyplot as plt
import numpy as np

mu, sigma = 50, 25

value1 = 1.5*mu + sigma*np.random.randn(100)
value2 = mu + 1.5*sigma*np.random.randn(100)
value3 = 0.5*mu + sigma*np.random.randn(100)
value4 = mu + 0.5*sigma*np.random.randn(100)

box_plot_data=[value1,value2,value3,value4]
plt.boxplot(box_plot_data)
plt.axhline(y=90, xmin=0.380, xmax=1)
plt.show()

Boxplot with ray

数据是随机的,颜色是默认值,但是想法是一样的。默认箱形图上的xrange[0, 1],每个箱形图均分成相等的区域。每个框位于其区域的中心,因此四个框的中心位于0.125、0.375,.625和0.875。

要在第二个箱形图的右边绘制一条水平线,可以使xmin的值大约为0.375。我说大概是因为matplotlib会根据线宽略微过度扩展,因此通常最好添加0.005(或一个数字,具体取决于您在axhline中使用的线宽)。这就是为什么我实际上使用xmin=0.380而不是xmin=0.375的原因。

答案 1 :(得分:-2)

我认为最简单的方法是绘制从(n,y0)(xend,y0)的线,其中xend是轴右边缘的坐标。可能会发现例如通过

xstart, xend = ax.get_xlim()

之后绘制了箱线图。 n是箱线图编号,y0是绘制线的y坐标(我想后者是已知的吗?) 对于n=2y0=90,绘制直线是直接的,

ax.plot([2,xend],[90,90])

完整示例(接管@davidlowryduda的答案中的箱线图例):

import numpy as np
import matplotlib.pyplot as plt

mu, sigma = 50, 25

value1 = 1.5*mu + sigma*np.random.randn(100)
value2 = mu + 1.5*sigma*np.random.randn(100)
value3 = 0.5*mu + sigma*np.random.randn(100)
value4 = mu + 0.5*sigma*np.random.randn(100)

box_plot_data=[value1,value2,value3,value4]

fig,ax = plt.subplots()
ax.boxplot(box_plot_data)

xstart, xend = ax.get_xlim()
ax.plot([2,xend],[90,90])
plt.show()

enter image description here

这样做的缺点是缩放或平移时不会保留该行。如果需要的话,需要使用a callback

import numpy as np
import matplotlib.pyplot as plt

mu, sigma = 50, 25

value1 = 1.5*mu + sigma*np.random.randn(100)
value2 = mu + 1.5*sigma*np.random.randn(100)
value3 = 0.5*mu + sigma*np.random.randn(100)
value4 = mu + 0.5*sigma*np.random.randn(100)

box_plot_data=[value1,value2,value3,value4]

fig,ax = plt.subplots()
ax.boxplot(box_plot_data)

xstart, xend = ax.get_xlim()
line, = ax.plot([2,xend],[90,90])

def callback(evt):
    xstart, xend = ax.get_xlim()
    line.set_xdata((2,xend))

ax.callbacks.connect('xlim_changed', callback)

plt.show()

通过此操作,即使缩放或平移后,线条仍保持在应有的位置。

另一种选择是增强ConnectionPatch以允许任意变换,这样您就可以提供将x坐标作为轴坐标,将y坐标作为坐标的变换数据坐标。此转换由ax.get_yaxis_transform()给出。借助下面显示的子类ConnectionPatch,无需回调即可实现与上述相同的功能。

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import ConnectionPatch

class EnhancedConnector(ConnectionPatch):
    def _get_xy(self, x, y, s, axes=None):
        p = super()._get_xy(x, y, s, axes=axes)
        if p is None:
            return s.transform_point((x, y))
        else:
            return p

mu, sigma = 50, 25

value1 = 1.5*mu + sigma*np.random.randn(100)
value2 = mu + 1.5*sigma*np.random.randn(100)
value3 = 0.5*mu + sigma*np.random.randn(100)
value4 = mu + 0.5*sigma*np.random.randn(100)

box_plot_data=[value1,value2,value3,value4]

fig,ax = plt.subplots()
ax.boxplot(box_plot_data)

transB = ax.get_yaxis_transform() 
p = EnhancedConnector(xyA=(2,90), xyB=(1,90), coordsA="data", coordsB=transB, 
                    axesA=ax, axesB=ax)
ax.add_patch(p)

plt.show()