【问题标题】:Labelling a matplotlib histogram bin with an arrow用箭头标记 matplotlib 直方图箱
【发布时间】:2016-03-03 18:24:56
【问题描述】:

我有一个可以用下面的 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)

创建这样的情节:

对于给定的整数,我将如何用箭头标记 bin?

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

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

【问题讨论】:

    标签: python matplotlib annotate


    【解决方案1】:

    您可以使用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"
    

    【讨论】:

    • 感谢回复,进一步扩展这个问题是否可以根据bin的高度自动设置箭头的y位置?
    • @BML91 是的,有可能……让我编辑我的答案
    • 效果很好。谢谢你。我正在查看文档以更改箭头线的粗细,我似乎找不到任何东西 - 你能否指出我正确的方向?
    • 我看到arrowprops()width 关键字,但是当我尝试使用它时我得到一个AttributeError: Unknown property width
    • @BML91: width 在下面的解决方案中运行良好(我更新了我的代码)。对于这个答案,您必须使用 lw 而不是 width isside arrowprops();那么它就可以正常工作了。
    【解决方案2】:

    我认为@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):

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-12-14
      • 1970-01-01
      • 2021-04-24
      • 1970-01-01
      • 2014-11-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多