【问题标题】:Double y axis for multiple columns in MatplotlibMatplotlib中多列的双y轴
【发布时间】:2023-03-04 17:09:01
【问题描述】:

我想在条形图中显示以下数据框,但使用双 y axis,我想在左侧显示 areas 列,在右侧显示 prices 列:

             area1      area2        price1      price2
level               
first       263.16      906.58      10443.32     35101.88
second      6879.83    14343.03      2077.79     4415.53
third      31942.75    60864.24       922.87     1774.47

我尝试了下面的代码,它可以工作但只显示左侧。

import matplotlib.pyplot as plt

df.plot(kind='bar')
plt.xticks(rotation=45, fontproperties="SimHei")
plt.xlabel("")
plt.legend()

谢谢。

【问题讨论】:

    标签: python python-3.x matplotlib plot bar-chart


    【解决方案1】:

    如果我理解正确,一种方法可能是这样,但你必须“玩”一下刻度的宽度和位置值:

    import pandas as pd
    import matplotlib.pyplot as plt
    
    fig = plt.figure(figsize=(12,5)) 
    ax = fig.add_subplot(111) 
    ax2 = ax.twinx() 
    
    width = 0.1
    
    df.area1.plot(kind='bar', color='red', ax=ax, width=width, position=0 )
    df.area2.plot(kind='bar', color='orange', ax=ax, width=width, position=1)
    df.price1.plot(kind='bar', color='blue', ax=ax2, width=width, position=2)
    df.price2.plot(kind='bar', color='green', ax=ax2, width=width, position=3)
    
    ax.set_ylabel('Area')
    ax2.set_ylabel('Price')
    ax.legend(["Area1", "Area2"], bbox_to_anchor=(0.8,1.0))
    ax2.legend(["Price1", "Price2"], bbox_to_anchor=(0.9,1.0))
    plt.show()
    

    另一种方式是这样的:

    import pandas as pd
    import matplotlib.pyplot as plt
    import numpy as np
    
    fig = plt.figure(figsize=(10,5)) 
    ax = fig.add_subplot(111) 
    ax2 = ax.twinx() 
    # ax.set_xticklabels(ax.get_xticklabels(),rotation=45) # Rotation 45 degrees
    
    width = 0.1
    ind = np.arange(len(df))
    
    ax.set_ylabel('Area')
    ax2.set_ylabel('Price')
    ax.set_xlabel('Level')
    ax.bar(ind, df.area1, width, color='red', label='area1')
    ax.bar(ind + width, df.area2, width, color='orange', label='area2')
    ax2.bar(ind + 2*width, df.price1, width, color='blue', label='price1')
    ax2.bar(ind + 3*width, df.price2, width, color='green', label='price2')
    
    ax.set(xticks=(ind + 1.5*width), xticklabels=df.index, xlim=[2*width - 1, len(df)])
    ax.legend(["Area1", "Area2"], bbox_to_anchor=(1,1))
    ax2.legend(["Price1", "Price2"], bbox_to_anchor=(1,0.87))
    
    plt.show()
    

    【讨论】:

    • 非常感谢,xticks 怎么可以旋转 45 度?我尝试使用plt.xticks(rotation=45)ax.xticks(rotation=45),两者都不起作用。
    • @ahbon 我已经用另一个解决方案更新了答案,请检查一下:)
    • @ahbon 将xticks旋转45度,在第二个选项中使用ax.set_xticklabels(ax.get_xticklabels(),rotation=45)
    • 这个怎么样? ax.set_xticklabels(df.index, rotation=45),我试过了,但是ax2xticks 位置不如预期,全部放在左侧。第一个还行,就是怪了。
    • ax.set_xticklabels(df.index, rotation=45) 也适合我