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

5

回答上一个问题:按小时对日期时间对象进行排序,然后将其可视化到直方图中

我需要为一个X轴值绘制3个条形图来表示观众数量。现在它们显示的是一分钟以下和以上的观众数量。我需要显示总体的观众数量。我已经有了数据框架,但我似乎无法使它们看起来正确。只有两个条形图时,没有问题,它看起来就像我想要的那样: I need to plot 3 bars for one X-axis value representing viewer counts.

与此相关的代码:

# 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而不仅仅是pandas索引输出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',两个宽度值都是绝对值和负数。但是我不知道如何在三个条形图中使其看起来正确。我没有找到任何关于这些条形图位置的参数。另外,我已经尝试使用plt.hist()函数,但我无法得到与plt.bar()函数相同的输出。
因此,我希望在上面显示的图形中左侧有第三个条形图,比其他两个条形图略宽一些。

“我没有找到任何关于条形图位置的参数。”这是因为你在第一个参数(hours)中完全控制着条形图的位置。与 Excel 相比,这似乎有些奇怪,直到你尝试在 Excel 中创建具有不均匀间距和不等宽度的条形图 :/ - Dan
2个回答

5

pandas 会自动为您完成这种对齐,如果您使用一步而不是两步(或三步)制作条形图。考虑以下示例(改编自文档,为每个动物添加第三个条形图)。

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()

enter image description here


感谢你指引我方向!实际上,昨天我已经尝试使用文档中的这个示例了几次,但是现在你再次确认了这就是方向,所以我更加努力地去推进。问题很明显,将数据框切片转换为列表后,这个简单而实用的解决方案有效地解决了问题。 - midi

4

在纯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 可能是一个很好的选择。你应该(几乎总是)尝试将你的数据保持为长格式,所以不要为短、中、长三个不同的数据框架,更好的做法是保持一个单一的数据框架,并添加一个列来标记每行为短、中或长。在Seaborn的 barplot 中使用这个新的列作为 hue 参数。

进入图像描述


谢谢Dan也跟进这个问题,非常感谢!我已经养成了使用pandas处理一切的习惯,正在努力掌握语法,以便能够使用数据框架解决问题,而不是纯粹的Python。 :) - midi
Pandas很棒,只是不要不必要地分割你的数据框。Seaborn与pandas非常配合。最后,除非你想对图表的外观有很多控制权,否则没有理由坚持使用纯matplotlib方法。 - Dan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接