我有一个Pandas DataFrame,其中有一个名为“AXLES”的列,它可以接受3-12之间的整数值。我试图使用Seaborn的countplot()选项来实现以下绘图:
1.左边的y轴显示了这些值在数据中出现的频率。轴延伸为[0%-100%],每10%处有刻度线。
1.右y轴示出了实际计数,值对应于由左y轴确定的刻度线(每隔10%标记)。
- x轴显示条形图的类别[3、4、5、6、7、8、9、10、11、12]。
1.条形图顶部的注解显示该类别的实际百分比。
下面的代码给出了下面的图表,有实际的计数,但我找不到一种方法将它们转换为频率。我可以使用df.AXLES.value_counts()/len(df.index)
获得频率,但我不确定如何将此信息插入Seaborn的countplot()
。
我还为注解找到了一个解决方案,但我不确定这是否是最好的实现。
任何帮助将不胜感激!
谢谢
plt.figure(figsize=(12,8))
ax = sns.countplot(x="AXLES", data=dfWIM, order=[3,4,5,6,7,8,9,10,11,12])
plt.title('Distribution of Truck Configurations')
plt.xlabel('Number of Axles')
plt.ylabel('Frequency [%]')
for p in ax.patches:
ax.annotate('%{:.1f}'.format(p.get_height()), (p.get_x()+0.1, p.get_height()+50))
编辑:
我通过下面的代码更接近我所需要的,使用Pandas的条形图,放弃Seaborn。感觉我使用了很多变通方法,必须有一种更简单的方法来做到这一点。这种方法的问题:
- 在Pandas的条形图函数中没有像Seaborn的countplot()那样的
order
关键字,所以我不能像在countplot()中那样绘制3-12的所有类别。即使该类别中没有数据,我也需要显示它们。 - 由于某些原因,第二个y轴会弄乱条形图和注解(请参见在文本和条形图上绘制的白色网格线)。
plt.figure(figsize=(12,8))
plt.title('Distribution of Truck Configurations')
plt.xlabel('Number of Axles')
plt.ylabel('Frequency [%]')
ax = (dfWIM.AXLES.value_counts()/len(df)*100).sort_index().plot(kind="bar", rot=0)
ax.set_yticks(np.arange(0, 110, 10))
ax2 = ax.twinx()
ax2.set_yticks(np.arange(0, 110, 10)*len(df)/100)
for p in ax.patches:
ax.annotate('{:.2f}%'.format(p.get_height()), (p.get_x()+0.15, p.get_height()+1))
3条答案
按热度按时间xa9qqrwz1#
您可以通过为频率创建一个
twinx
轴来完成此操作。您可以切换两个y轴,使频率保持在左侧,计数保持在右侧,但无需重新计算计数轴(这里我们使用tick_left()
和tick_right()
移动刻度,使用set_label_position
移动轴标签然后,您可以使用
matplotlib.ticker
模块(具体为ticker.MultipleLocator
和ticker.LinearLocator
)设置刻度。至于注解,您可以使用
patch.get_bbox().get_points()
获取条形图所有4个角的x和y位置。这与正确设置水平和垂直对齐沿着,意味着您不需要向注解位置添加任何任意偏移。最后,您需要关闭孪生轴的栅格,以防止栅格线显示在条形图的顶部(
ax2.grid(None)
)。下面是一个工作脚本:
bnlyeluc2#
我使用核心
matplotlib
的条形图让它工作。显然我没有你的数据,但根据你的数据调整它应该是直截了当的。方法
我使用了
matplotlib
的双轴,并将数据绘制为第二个Axes
对象上的条形图。其余的只是一些小动作,以获得正确的刻度并进行注解。希望这能帮上忙。
代码
vlurs2pr3#
我想你可以先手动设置y大刻度,然后修改每个标签