Matplotlib:使用 twinx 叠加时箱线图和条形图发生移动

问题描述 投票:0回答:2

当我创建条形图并使用 twin x 覆盖条形图时,与条形相比,框看起来向右移动了一位。

这个问题之前已经被识别过(Python pandas 绘制平移 x 轴,如果孪生两个 y 轴),但该解决方案似乎不再有效。 (我使用的是 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])

The problematic chart

输出显示与条形相比,框向右移动了一位。上一篇文章的受访者正确地指出,条形的刻度位置是从零开始的,而方框的刻度位置是从一开始的,这导致了偏移。然而,受访者用来修复该问题的

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 中。

这是理想的图表:

Ideal chart

非常感谢。

matplotlib boxplot twinx
2个回答
0
投票

您可以使用以下技巧:提供 x 值以将条形图从

x=1
开始放置。为此,请使用
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)

enter image description here


0
投票

positions类似数组,可选 盒子的位置。价格变动和限制会自动设置以匹配仓位。默认为 range(1, N+1),其中 N 是要绘制的框的数量。

箱线图的默认索引是 [1, len(df_gb['B'])],所以这样做

df.boxplot(column='B', by='A', ax=ax, position=[x for x in range(len(df_gb['B']))])

也能达到目的。

在此输入图片描述

© www.soinside.com 2019 - 2024. All rights reserved.