用箭头标记 matplotlib 直方图 bin

Labelling a matplotlib histogram bin with an arrow

我有一个直方图可以用下面的 MWE 复制:

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np

pd.Series(np.random.normal(0, 100, 1000)).plot(kind='hist', bins=50)

创建这样的情节:

然后我将如何为给定整数用箭头标记容器?

例如,见下文,箭头标记包含整数 300 的容器。

编辑:理想情况下,我应该添加箭头的 y 坐标应该由它标记的栏的高度自动设置 - 如果可能的话!

您可以使用annotate添加箭头:

import pandas as pd
import matplotlib.pyplot as plt
#import seaborn as sns
import numpy as np

fig, ax = plt.subplots()
series = pd.Series(np.random.normal(0, 100, 1000))
series.plot(kind='hist', bins=50, ax=ax)
ax.annotate("",
            xy=(300, 5), xycoords='data',
            xytext=(300, 20), textcoords='data',
            arrowprops=dict(arrowstyle="->",
                            connectionstyle="arc3"),
            )

在这个例子中,我添加了一个从坐标 (300, 20) 到 (300, 5) 的箭头。

为了自动将箭头缩放到 bin 中的值,您可以使用 matplotlib hist 绘制直方图并取回值,然后使用 numpy where 查找哪个 bin对应想要的位置。

import pandas as pd
import matplotlib.pyplot as plt
#import seaborn as sns
import numpy as np

nbins = 50
labeled_bin = 200

fig, ax = plt.subplots()

series = pd.Series(np.random.normal(0, 100, 1000))

## plot the histogram and return the bin position and values
ybins, xbins, _ = ax.hist(series, bins=nbins)

## find out in which bin belongs the position where you want the label
ind_bin = np.where(xbins >= labeled_bin)[0]
if len(ind_bin) > 0 and ind_bin[0] > 0:
    ## get position and value of the bin
    x_bin = xbins[ind_bin[0]-1]/2. + xbins[ind_bin[0]]/2.
    y_bin = ybins[ind_bin[0]-1]
    ## add the arrow
    ax.annotate("",
                xy=(x_bin, y_bin + 5), xycoords='data',
                xytext=(x_bin, y_bin + 20), textcoords='data',
                arrowprops=dict(arrowstyle="->",
                                connectionstyle="arc3"),
                                )
else:
    print "Labeled bin is outside range"

@Julien Spronck 展示了我认为的最佳方式。或者,您也可以使用 arrow;示例代码可以在下面找到。 y 坐标是通过计算某个 bin 中有多少元素自动确定的(具有您可以自己定义的特定公差)。您可以使用参数(箭头长度,箭头长度)。这是代码:

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np

mySer = pd.Series(np.random.normal(0, 100, 1000))
mySer.plot(kind='hist', bins=50)

# that is where you want to add the arrow
ind = 200
# determine how many elements you have in the bin (with a certain tolerance)
n = len(mySer[(mySer > ind*0.95) & (mySer <  ind*1.05)])

# define length of the arrow
lenArrow = 10
lenHead = 2
wiArrow = 5
plt.arrow(ind, n+lenArrow+lenHead, 0, -lenArrow, head_width=wiArrow+3, head_length=lenHead, width=wiArrow, fc='k', ec='k')

plt.show()

这将为您提供以下输出(对于 200 而不是您示例中的 300):