【问题标题】:Matplotlib: Lines on Top of Bars, Legend on the Left, No SplinesMatplotlib:条形顶部的线条,左侧的图例,没有样条线
【发布时间】:2020-01-21 01:09:26
【问题描述】:

我无法调整下面的图表。

数据框如下所示:

   Year  Some  All     Ratio
0  2016     9  157  0.057325
1  2017    13  189  0.068783
2  2018    21  216  0.097222
3  2019    18  190  0.094737
4  2020    28  284  0.098592

这是我想做的:

  • 橙色线应位于条形前面。我尝试使用 zorder 参数,但没有帮助。我还尝试切换轴对象的顺序,但它没有做任何事情。
  • 我想要左边的图例。您会在下面的代码中注意到我使用了一个有点大的figsize 参数。如果我使用较小的,图例会神奇地向左移动,但我不想使用较小的。
  • 我想用相应的值标记每个条形顶部的条形图。我尝试遍历每个值并使用ax.annotate 单独注释条形,但我无法自动将值居中。在这个最小的示例中,所有值都是三位数长,但在原始数据中,我有四位数长的数字,我找不到一个很好的方法让它在所有这些数字中居中。
  • 最后,我想去掉顶部和右侧的刺。我的代码如下 由于某种原因没有删除它们。

帮助人们入门的代码如下。

data = {'Year': {0: '2016', 1: '2017', 2: '2018', 3: '2019', 4: '2020'},
 'Some': {0: 9, 1: 13, 2: 21, 3: 18, 4: 28},
 'All': {0: 157, 1: 189, 2: 216, 3: 190, 4: 284},
 'Ratio': {0: 0.05732484076433121,
  1: 0.06878306878306878,
  2: 0.09722222222222222,
  3: 0.09473684210526316,
  4: 0.09859154929577464}}

df = __import__("pandas").DataFrame(data)

ax = df.plot(x="Year", y="Ratio",
                 kind="line", linestyle='-', marker='o', color="orange",
                 figsize=((24,12))
                )
df.plot(x="Year", y="All",
            kind="bar", ax=ax, secondary_y=True
           )

ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)

【问题讨论】:

    标签: python pandas matplotlib


    【解决方案1】:

    以下答案是从这个答案中复制而来的。

    import pandas as pd
    from matplotlib import pyplot as plt
    
    data = {'Year': {0: '2016', 1: '2017', 2: '2018', 3: '2019', 4: '2020'},
            'Some': {0: 9, 1: 13, 2: 21, 3: 18, 4: 28},
            'All': {0: 157, 1: 189, 2: 216, 3: 190, 4: 284},
            'Ratio': {0: 0.05732484076433121,
                      1: 0.06878306878306878,
                      2: 0.09722222222222222,
                      3: 0.09473684210526316,
                      4: 0.09859154929577464}}
    
    df = pd.DataFrame(data)
    
    ax1 = df.plot(x="Year", y="All",
                  kind="bar",
                  )
    for i, a in df.All.items():
        ax1.text(i, a, str(a), ha='center', va='bottom', fontsize=18)
    xlims = ax1.get_xlim()
    
    ax2 = df.plot(x="Year", y="Ratio",
                  kind="line", linestyle='-', marker='o', color="orange", ax=ax1, secondary_y=True,
                  figsize=((24, 12))
                  )
    ax2.set_xlim(xlims)  # needed because the line plot shortens the xlims
    
    # ax1.get_legend().set_bbox_to_anchor((0.03, 0.9, 0.1, 0.1)) # unpredictable behavior when loc='best'
    # ax1.legend(loc='upper left') # in our case, this would create a second legend
    
    ax1.get_legend().remove() # remove badly placed legend
    handles1, labels1 = ax1.get_legend_handles_labels()
    handles2, labels2 = ax2.get_legend_handles_labels()
    ax1.legend(handles=handles1 + handles2,   # create a new legend
               labels=labels1 + labels2,
               loc='upper left')
    
    # ax1.yaxis.tick_right()  # place the yticks for ax1 at the right
    ax2.yaxis.tick_left()  # place the yticks for ax2 at the left
    ax2.set_ylabel('Ratio')
    ax2.yaxis.set_label_position('left')
    ax1.axes.yaxis.set_ticks([]) # remove ticks
    
    for ax in (ax1, ax2):
        for where in ('top', 'right'):
            ax.spines[where].set_visible(False)
    
    plt.show()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-04
      • 2016-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-18
      • 2011-03-24
      • 1970-01-01
      相关资源
      最近更新 更多