【问题标题】:Matplotlib: Boxplot and bar chart shifted when overlaid using twinxMatplotlib:箱线图和条形图在使用 twinx 覆盖时发生偏移
【发布时间】:2021-10-14 17:18:56
【问题描述】:

当我创建一个条形图并使用双 x 覆盖条形图时,与条形相比,这些框向右移动了一个。

之前已发现此问题 (Python pandas plotting shift x-axis if twinx two y-axes),但该解决方案似乎不再有效。 (我使用的是 Matplotlib 3.1.0)

li_str = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']

df = pd.DataFrame([[i]+j[k] for i,j in {li_str[i]:np.random.randn(j,2).tolist() for i,j in \
    enumerate(np.random.randint(5, 15, len(li_str)))}.items() for k in range(len(j))]
    , columns=['A', 'B', 'C'])

fig, ax = plt.subplots(figsize=(16,6))
ax2 = ax.twinx()
df_gb = df.groupby('A').count()
p1 = df.boxplot(ax=ax, column='B', by='A', sym='')
p2 = df_gb['B'].plot(ax=ax2, kind='bar', figsize=(16,6)
    , colormap='Set2', alpha=0.3, secondary_y=True)
plt.ylim([0, 20])

输出显示与条相比向右移动了一个框。上一篇文章的受访者正确地指出,柱的刻度位置是从零开始的,而方框的刻度位置是从一开始的,这导致了这种转变。但是,响应者用来修复它的plt.bar() 方法现在会引发错误,因为 x 参数已成为强制性的。如果提供了 x 参数,它仍然会引发错误,因为不再有参数“left”。

df.boxplot(column='B', by='A')
plt.twinx()
plt.bar(left=plt.xticks()[0], height=df.groupby('A').count()['B'],
  align='center', alpha=0.3)

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-186-e257461650c1> in <module>
     26 plt.twinx()
     27 plt.bar(left=plt.xticks()[0], height=df.groupby('A').count()['B'],
---> 28         align='center', alpha=0.3)

TypeError: bar() missing 1 required positional argument: 'x'

此外,我更喜欢使用面向对象的方法参考轴进行修复,因为我想将图表放入交互式 ipywidget。

这是理想的图表:

非常感谢。

【问题讨论】:

    标签: matplotlib boxplot twinx


    【解决方案1】:

    您可以使用以下技巧:提供从 x=1 开始放置条形的 x 值。为此,请使用 range(1, len(df_gb['B'])+1) 作为 x 值。

    fig, ax = plt.subplots(figsize=(8, 4))
    ax2 = ax.twinx()
    df_gb = df.groupby('A').count()
    df.boxplot(column='B', by='A', ax=ax)
    ax2.bar(range(1, len(df_gb['B'])+1), height=df_gb['B'],align='center', alpha=0.3)
    

    【讨论】:

    • 巧妙的简单技巧。谢谢你。但是您知道如何使用面向对象进行此更改吗?我试过了
    • “使用面向对象进行此更改”到底是什么意思?您的意思是从轴对象中获取数据以放置条形?
    • 对不起,我是论坛的新人,可能无法很好地表达自己。我想通过 ax2=ax.twinx() 将孪生轴分配给一个对象,然后在通过 pandas 包装器发生事件时灵活地将条形分配给 ax2:df.bar(ax=ax2)。我试过 ax2.set_xticks(ax2.get_xticks()+1),但这似乎只是改变了标签,而不是条形。
    • @nostalghia :检查我的编辑。我基本上用ax2替换了最后一行中的plt。你指的是这个吗?
    • 感谢您的努力。它看起来更像我所追求的。只是这里已经太晚了。我需要睡一会儿才能清醒。明天早上我会检查并确认。干杯。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-12
    • 2010-12-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多