Python matplotlib 多条
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14270391/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Python matplotlib multiple bars
提问by John Smith
How to plot multiple bars in matplotlib, when I tried to call the bar function multiple times, they overlap and as seen the below figure the highest value red can be seen only. How can I plot the multiple bars with dates on the x-axes?
如何在 matplotlib 中绘制多个条形图,当我尝试多次调用 bar 函数时,它们重叠,如下图所示,只能看到最高值红色。如何在 x 轴上绘制带有日期的多个条形图?
So far, I tried this:
到目前为止,我试过这个:
import matplotlib.pyplot as plt
import datetime
x = [
datetime.datetime(2011, 1, 4, 0, 0),
datetime.datetime(2011, 1, 5, 0, 0),
datetime.datetime(2011, 1, 6, 0, 0)
]
y = [4, 9, 2]
z = [1, 2, 3]
k = [11, 12, 13]
ax = plt.subplot(111)
ax.bar(x, y, width=0.5, color='b', align='center')
ax.bar(x, z, width=0.5, color='g', align='center')
ax.bar(x, k, width=0.5, color='r', align='center')
ax.xaxis_date()
plt.show()
I got this:
我懂了:


The results should be something like, but with the dates are on the x-axes and bars are next to each other:
结果应该是这样的,但日期在 x 轴上,条形彼此相邻:


采纳答案by HYRY
import matplotlib.pyplot as plt
from matplotlib.dates import date2num
import datetime
x = [
datetime.datetime(2011, 1, 4, 0, 0),
datetime.datetime(2011, 1, 5, 0, 0),
datetime.datetime(2011, 1, 6, 0, 0)
]
x = date2num(x)
y = [4, 9, 2]
z = [1, 2, 3]
k = [11, 12, 13]
ax = plt.subplot(111)
ax.bar(x-0.2, y, width=0.2, color='b', align='center')
ax.bar(x, z, width=0.2, color='g', align='center')
ax.bar(x+0.2, k, width=0.2, color='r', align='center')
ax.xaxis_date()
plt.show()


I don't know what's the "y values are also overlapping" means, does the following code solve your problem?
我不知道“y 值也重叠”是什么意思,以下代码是否解决了您的问题?
ax = plt.subplot(111)
w = 0.3
ax.bar(x-w, y, width=w, color='b', align='center')
ax.bar(x, z, width=w, color='g', align='center')
ax.bar(x+w, k, width=w, color='r', align='center')
ax.xaxis_date()
ax.autoscale(tight=True)
plt.show()


回答by John Lyon
The trouble with using dates as x-values, is that if you want a bar chart like in your second picture, they are going to be wrong. You should either use a stacked bar chart (colours on top of each other) or group by date (a "fake" date on the x-axis, basically just grouping the data points).
使用日期作为 x 值的麻烦在于,如果您想要像第二张图片中那样的条形图,它们将是错误的。您应该使用堆积条形图(颜色相互叠加)或按日期分组(x 轴上的“假”日期,基本上只是对数据点进行分组)。
import numpy as np
import matplotlib.pyplot as plt
N = 3
ind = np.arange(N) # the x locations for the groups
width = 0.27 # the width of the bars
fig = plt.figure()
ax = fig.add_subplot(111)
yvals = [4, 9, 2]
rects1 = ax.bar(ind, yvals, width, color='r')
zvals = [1,2,3]
rects2 = ax.bar(ind+width, zvals, width, color='g')
kvals = [11,12,13]
rects3 = ax.bar(ind+width*2, kvals, width, color='b')
ax.set_ylabel('Scores')
ax.set_xticks(ind+width)
ax.set_xticklabels( ('2011-Jan-4', '2011-Jan-5', '2011-Jan-6') )
ax.legend( (rects1[0], rects2[0], rects3[0]), ('y', 'z', 'k') )
def autolabel(rects):
for rect in rects:
h = rect.get_height()
ax.text(rect.get_x()+rect.get_width()/2., 1.05*h, '%d'%int(h),
ha='center', va='bottom')
autolabel(rects1)
autolabel(rects2)
autolabel(rects3)
plt.show()


回答by Dave
I did this solution: if you want plot more than one plot in one figure, make sure before plotting next plots you have set right matplotlib.pyplot.hold(True)to able adding another plots.
我做了这个解决方案:如果您想在一个图中绘制多个图,请确保在绘制下一个图之前您已设置matplotlib.pyplot.hold(True)为能够添加另一个图。
About datetime values on X axe, solution using alignment of bars works for me. When you create another bar plot with matplotlib.pyplot.bar(), just use align='edge|center'and set width='+|-distance'.
关于 X 轴上的日期时间值,使用条形对齐的解决方案对我有用。当您创建另一个条形图时matplotlib.pyplot.bar(),只需使用align='edge|center'并设置width='+|-distance'。
When you set all bars (plots) right, you will see bars fine.
当您正确设置所有条形(图)时,您会看到条形很好。
回答by liwt31
I know that this is about matplotlib, but using pandasand seaborncan save you a lot of time:
我知道这是关于matplotlib,但是使用pandas和seaborn可以为您节省大量时间:
df = pd.DataFrame(zip(x*3, ["y"]*3+["z"]*3+["k"]*3, y+z+k), columns=["time", "kind", "data"])
plt.figure(figsize=(10, 6))
sns.barplot(x="time", hue="kind", y="data", data=df)
plt.show()
回答by pascscha
after looking for a similar solution and not finding anything flexible enough, I decided to write my own function for it. It allows you to have as many bars per group as you wish and specify both the width of a group as well as the individual widths of the bars within the groups.
在寻找类似的解决方案并没有找到任何足够灵活的解决方案后,我决定为它编写自己的函数。它允许您根据需要为每个组设置尽可能多的条形,并指定组的宽度以及组内条形的单个宽度。
Enjoy:
享受:
from matplotlib import pyplot as plt
def bar_plot(ax, data, colors=None, total_width=0.8, single_width=1, legend=True):
"""Draws a bar plot with multiple bars per data point.
Parameters
----------
ax : matplotlib.pyplot.axis
The axis we want to draw our plot on.
data: dictionary
A dictionary containing the data we want to plot. Keys are the names of the
data, the items is a list of the values.
Example:
data = {
"x":[1,2,3],
"y":[1,2,3],
"z":[1,2,3],
}
colors : array-like, optional
A list of colors which are used for the bars. If None, the colors
will be the standard matplotlib color cyle. (default: None)
total_width : float, optional, default: 0.8
The width of a bar group. 0.8 means that 80% of the x-axis is covered
by bars and 20% will be spaces between the bars.
single_width: float, optional, default: 1
The relative width of a single bar within a group. 1 means the bars
will touch eachother within a group, values less than 1 will make
these bars thinner.
legend: bool, optional, default: True
If this is set to true, a legend will be added to the axis.
"""
# Check if colors where provided, otherwhise use the default color cycle
if colors is None:
colors = plt.rcParams['axes.prop_cycle'].by_key()['color']
# Number of bars per group
n_bars = len(data)
# The width of a single bar
bar_width = total_width / n_bars
# List containing handles for the drawn bars, used for the legend
bars = []
# Iterate over all data
for i, (name, values) in enumerate(data.items()):
# The offset in x direction of that bar
x_offset = (i - n_bars / 2) * bar_width + bar_width / 2
# Draw a bar for every value of that type
for x, y in enumerate(values):
bar = ax.bar(x + x_offset, y, width=bar_width * single_width, color=colors[i % len(colors)])
# Add a handle to the last drawn bar, which we'll need for the legend
bars.append(bar[0])
# Draw legend if we need
if legend:
ax.legend(bars, data.keys())
if __name__ == "__main__":
# Usage example:
data = {
"a": [1, 2, 3, 2, 1],
"b": [2, 3, 4, 3, 1],
"c": [3, 2, 1, 4, 2],
"d": [5, 9, 2, 1, 8],
"e": [1, 3, 2, 2, 3],
"f": [4, 3, 1, 1, 4],
}
fig, ax = plt.subplots()
bar_plot(ax, data, total_width=.8, single_width=.9)
plt.show()
Output:
输出:

