使用 ax.bar() 使用 matplotlib 绘制多个条形图

Posted

技术标签:

【中文标题】使用 ax.bar() 使用 matplotlib 绘制多个条形图【英文标题】:Plotting multiple bars with matplotlib using ax.bar() 【发布时间】:2019-09-28 07:16:57 【问题描述】:

跟进我之前的问题:Sorting datetime objects by hour to a pandas dataframe then visualize to histogram

我需要为一个代表观众人数的 X 轴值绘制 3 个条形图。现在他们显示不到一分钟及以上的内容。我需要一个显示整体观众。我有数据框,但我似乎无法让它们看起来正确。只有 2 条我没有问题,看起来就像我想要有两条条一样:

代码的相关部分:

# Time and date stamp variables
allviews = int(df['time'].dt.hour.count())
date = str(df['date'][0].date())
hours = df_hist_short.index.tolist()
hours[:] = [str(x) + ':00' for x in hours]

我用来表示 X 轴的小时变量可能有问题,因为我将它转换为字符串,所以我可以使小时看起来像 23:00 而不仅仅是熊猫索引输出 23 等。我有看到人们从 X 中添加或减去值以更改条形位置的示例。

fig, ax = plt.subplots(figsize=(20, 5))
short_viewers = ax.bar(hours, df_hist_short['time'], width=-0.35, align='edge')
long_viewers = ax.bar(hours, df_hist_long['time'], width=0.35, align='edge')

现在我设置align='edge',两个宽度值是绝对值和负值。但我不知道如何使它看起来与 3 条正确。我没有找到任何关于酒吧的定位论据。我也尝试使用 plt.hist() 但我无法获得与 plt.bar() 函数相同的输出。

因此,我希望在上图左侧显示第三条,比其他两条宽一点。

【问题讨论】:

“我没有找到任何条形定位参数。” - 这是因为您可以完全控制第一个参数(您的 hours)中柱的位置。与 Excel 之类的东西相比,这似乎是一个奇怪的麻烦,直到您尝试在 Excel 中创建一个间距不均匀且条宽不等的条形图:/ 【参考方案1】:

pandas 将为您完成此对齐,如果您一步制作条形图而不是两个(或三个)。考虑这个例子(改编自docs,为每只动物添加第三条)。

import pandas as pd
import matplotlib.pyplot as plt

speed = [0.1, 17.5, 40, 48, 52, 69, 88]
lifespan = [2, 8, 70, 1.5, 25, 12, 28]
height = [1, 5, 20, 3, 30, 6, 10]
index = ['snail', 'pig', 'elephant',
         'rabbit', 'giraffe', 'coyote', 'horse']
df = pd.DataFrame('speed': speed,
                   'lifespan': lifespan,
                   'height': height, index=index)
ax = df.plot.bar(rot=0)

plt.show()

【讨论】:

感谢您为我指明方向!实际上我昨天已经尝试过几次文档中的这个例子,但现在你向我保证这是方向,所以我更加努力了。问题很明显,这个简单实用的解决方案在我将数据帧切片转换为列表后起作用。【参考方案2】:

在纯 matplotlib 中,您可以调整绘图的 x 值,而不是使用宽度参数来定位条形:

import numpy as np
import matplotlib.pyplot as plt

# Make some fake data:
n_series = 3
n_observations = 5
x = np.arange(n_observations)
data = np.random.random((n_observations,n_series))


# Plotting:

fig, ax = plt.subplots(figsize=(20,5))

# Determine bar widths
width_cluster = 0.7
width_bar = width_cluster/n_series

for n in range(n_series):
    x_positions = x+(width_bar*n)-width_cluster/2
    ax.bar(x_positions, data[:,n], width_bar, align='edge')

在您的特定情况下,seaborn 可能是一个不错的选择。您应该(几乎总是)尝试将您的数据保存在long-form 中,因此与其将三个单独的数据框分别用于短、中和长,不如保留一个数据框并添加一个将每一行标记为短的列,中或长。将此新列用作 Seaborn 的 barplot 中的 hue 参数

【讨论】:

感谢 Dan 也跟进这个问题,非常感谢!我刚刚养成了使用 pandas 来处理所有事情的习惯,我正在努力学习语法,所以我会在数据帧而不是纯 python 中提出解决方案。 :) Pandas 很棒,只是不要不必要地拆分您的 DataFrame。 Seaborn 与熊猫配合得很好。最后,除非您想对图表的外观进行大量控制,否则您可能没有理由坚持使用纯 matplotlib 方法。

以上是关于使用 ax.bar() 使用 matplotlib 绘制多个条形图的主要内容,如果未能解决你的问题,请参考以下文章

如何在 matplotlib 中为 3D 条形图创建图例?

无输出:使用 Matplotlib 的条形图

如何在 matplotlib 条形图中增加误差线的粗细?

使用 MatPlotLib 将多个条形图绘制成图表

条形图 Matplotlib:日期间隔(xaxis)问题与 twinx

5.4 实对称矩阵的对角化