代码之家  ›  专栏  ›  技术社区  ›  XyledMonkey

Matplotlib在条形图上方放置x记号

  •  0
  • XyledMonkey  · 技术社区  · 7 年前

    有没有办法将x记号放在堆叠条形图中每个堆叠条形图的上方,而不是放在x轴的下方?要明确的是,我的意思不是将x记号放在单个堆叠条中每个单独条的上方,我的意思是将x记号放在堆叠条本身的上方。以下是我创建情节的方式:

    df = pd.DataFrame(np.random.randint(1, 5, size=(3200, 3)))    
    df.loc[np.random.choice(df.index, size=3190, replace=False), :] = 0
    
    df_select = df[df.sum(axis=1)>1]
    fig, ax = plt.subplots()
    
    ax.bar(df_select.index, df_select.iloc[:,0], label = df_select.columns[0], wdith = 15)
    
    if df_select.shape[1] > 1:
        for i in range(1, df_select.shape[1]):
            bottom = df_select.iloc[:,np.arange(0,i,1)].sum(axis=1)
            ax.bar(df_select.index, df_select.iloc[:,i], bottom=bottom, label = 
    df_select.columns[i], width = 15)
    
    ax.set_xticks(df_select.index)
    plt.legend(loc='best', bbox_to_anchor=(1, 0.5))
    plt.xticks(rotation=90, fontsize=8) #this puts the x ticks below the x axis
    

    此外,我想在x轴的特定点放置一些文本。我将这些网站存储在列表中:

    sites = [19, 173, 1002] # the number and elements of this list vary
    

    因此,例如,在x=173时,我想在位置173处放置文本“site(173)”和一个勾号。

    为了供您参考,我发布了我当前代码生成的内容以及我想要生成的内容的图像: 当前: https://i.stack.imgur.com/QDlEP.png 目标: https://i.stack.imgur.com/IJJo4.png

    2 回复  |  直到 7 年前
        1
  •  2
  •   DavidG    7 年前

    这可以通过使用@Evan在此评论中链接的示例来实现,即 this one . 重要的一点是名为 autolabel 在链接的示例中。将显示的值从y轴值更改为x轴值很容易,请替换 height 具有 rect.get_x() . 更棘手的是将值放在条的顶部。通过对数据框中的值求和,可以找到条的总高度。

    heights = df_select.iloc[:,:].sum(axis=1)
    

    然后需要将其传递给autolabel函数,并用作条形图的高度。可以使用删除x记号标签

    ax.get_xaxis().set_ticklabels([])
    

    您可以在特定站点的x轴下方添加更多文本,只需使用 ax.text 使用的内容 sites 作为x位置,并将y位置设置为低于轴(-0.5或其他)。

    综上所述,我们得到以下工作示例:

    def autolabel(rects, heights):
        """
        Attach a text label above each bar displaying its height
        Modified for use with a stacked bar chart
        """
        for i, rect in enumerate(rects):
            x = rect.get_x()
            wid = rect.get_width()
            height = heights.values[i]
    
            ax.text(x + wid/2., 1.05*height,
                    '%d' % (int(x) + int((wid/2)+0.5)),
                    ha='center', va='bottom', rotation=90)
    
    
    df = pd.DataFrame(np.random.randint(1, 5, size=(3200, 3)))    
    df.loc[np.random.choice(df.index, size=3190, replace=False), :] = 0
    
    df_select = df[df.sum(axis=1)>1]
    fig, ax = plt.subplots()
    
    ax.bar(df_select.index, df_select.iloc[:,0], label = df_select.columns[0], width = 15)
    
    if df_select.shape[1] > 1:
        for i in range(1, df_select.shape[1]):
            bottom = df_select.iloc[:,np.arange(0,i,1)].sum(axis=1)
            rects1 = ax.bar(df_select.index, df_select.iloc[:,i], bottom=bottom, label = 
    df_select.columns[i], width = 15)
    
    ax.set_xticks(df_select.index)
    ax.get_xaxis().set_ticklabels([])   # turn off the x tick labels
    
    plt.legend(loc='best', bbox_to_anchor=(1, 0.5))
    
    heights = df_select.iloc[:, :].sum(axis=1)
    autolabel(rects1, heights)
    
    # Select 3 random value to add labels below the x axis. Make sure they are
    # within the axis limits
    sites = np.random.choice(df_select.index, 3)
    
    for site in sites:
        ax.text(site, -0.5,
            'site(%s)' % site,
            ha='center', va='bottom',fontsize=6)
    
    plt.show()
    

    给出了以下图表:

    enter image description here

    注: 这有时看起来很凌乱,因为这些条非常细且分散,并且可以彼此靠近,这意味着值可能开始重叠。

        2
  •  0
  •   Peter Leimbigler    7 年前

    如果您的意思是在身材框架的顶部设置x-tick标签,请尝试 ax.xaxis.tick_top() 在当前代码的底部。

    在自定义x轴位置放置文字标签的步骤:基于 these docs ,这应该可以:

    locs, labels = plt.xticks(rotation=90, fontsize=8)
    sites = [19, 173, 1002]
    site_labels = ['label at 19', 'label at 173', 'label at 1002']
    new_locs = np.append(locs, sites)
    new_labels = np.append(labels, site_labels)
    plt.xticks(new_locs, new_labels)