Python 如何在matplotlib中绘制5组条形图?

Python 如何在matplotlib中绘制5组条形图?,python,python-3.x,matplotlib,plot,bar-chart,Python,Python 3.x,Matplotlib,Plot,Bar Chart,我有以下数据帧: meteo = [["January", 9.2, 13.6, 4.7, 37, 70], ["February",9.9, 14.3, 5.4, 35, 70], ["March", 11.8, 16.1, 7.4, 36, 70], ["April", 13.7, 18.0, 9.4, 40, 69], ["May", 16.9, 21.1, 12.8, 47, 70], ["June", 20.9, 24.9, 16.8, 30, 68], ["July", 23.9,

我有以下数据帧:

meteo = [["January", 9.2, 13.6, 4.7, 37, 70],
["February",9.9, 14.3, 5.4, 35, 70],
["March", 11.8, 16.1, 7.4, 36, 70],
["April", 13.7, 18.0, 9.4, 40, 69],
["May", 16.9, 21.1, 12.8, 47, 70],
["June", 20.9, 24.9, 16.8, 30, 68],
["July", 23.9, 28.0, 19.8, 21, 67],
["August", 24.4, 28.5, 20.2, 62, 68],
["September", 21.7, 26.0, 17.4, 81, 70],
["October", 17.8, 22.1, 13.5, 91, 73],
["November", 13.0, 17.3, 8.6, 59, 71],
["December", 10.0, 14.3, 5.7, 40, 69]]

import pandas as pd

# Create dataframe with above data

df = pd.DataFrame(meteo)

# Drop useless column

df.drop(0, inplace = True, axis = 1)

# Rename columns

df.rename(columns = {1: "Temp_media_anual_mes", 2: "Temp_máxima_media", 3: "Temp_mínima_media", 4: "Media_lluvias_mensual", 5:"Humedad_media_rel"}, inplace = True)
df["mes"] = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
现在,我想绘制一个分组条形图。我希望每个月有5组酒吧。我已经试过了,但我对条之间的间距有点问题:

# Setting the positions and width for the bars
pos = list(range(len(df.mes))) 
width = 0.25 

# Plotting the bars
fig, ax = plt.subplots(figsize=(16,10))

# Create a bar with pre_score data,
# in position pos,
plt.bar(pos, 
        #using df['pre_score'] data,
        df['Temp_media_anual_mes'], 
        # of width
        width, 
        # with alpha 0.5
        alpha=0.5, 
        # with color
        color='red')
        # with label the first value in first_name
        #label=df['first_name'][0]) 

# Create a bar with mid_score data,
# in position pos + some width buffer,
plt.bar([p + width for p in pos], 
        #using df['mid_score'] data,
        df['Temp_máxima_media'],
        # of width
        width, 
        # with alpha 0.5
        alpha=0.5, 
        # with color
        color='green')
        # with label the second value in first_name
        #label=df['first_name'][1]) 

# Create a bar with post_score data,
# in position pos + some width buffer,
plt.bar([p + width*2 for p in pos], 
        #using df['post_score'] data,
        df['Temp_mínima_media'], 
        # of width
        width, 
        # with alpha 0.5
        alpha=0.5, 
        # with color
        color='blue')
        # with label the third value in first_name
        #label=df['first_name'][2]) 

plt.bar([p + width*2 for p in pos], 
        #using df['post_score'] data,
        df['Media_lluvias_mensual'], 
        # of width
        width, 
        # with alpha 0.5
        alpha=0.5, 
        # with color
        color='orange')
        # with label the third value in first_name
        #label=df['first_name'][2]) 

plt.bar([p + width*2 for p in pos], 
        #using df['post_score'] data,
        df['Humedad_media_rel'], 
        # of width
        width, 
        # with alpha 0.5
        alpha=0.5, 
        # with color
        color='purple')
        # with label the third value in first_name
        #label=df['first_name'][2]) 

# Set the y axis label
ax.set_ylabel('Ammount')

# Set the chart's title
ax.set_title('Rain and temperature')

# Set the position of the x ticks
ax.set_xticks([p + 1.5 * width for p in pos])

# Set the labels for the x ticks
ax.set_xticklabels(df['mes'])

# Setting the x-axis and y-axis limits
plt.xlim(min(pos)-width, max(pos)+width*4)
plt.ylim([0, max(df['Temp_media_anual_mes'] + df['Temp_máxima_media'] + df['Temp_mínima_media'] + df["Media_lluvias_mensual"] + df["Humedad_media_rel"])] )

plt.grid()
plt.show()
这就是我得到的情节

如你所见,它显示了3个独立的栏,在第三个栏中,有3个栏一个接一个。我知道问题在于两条线之间的间距,但我不知道如何解决。有人能给我指一下正确的方向吗

编辑:

我还想在每个条的上方显示每个标绘值的测量单位。这些是:

  • 摄氏温度
  • mm表示降水量
  • %相对湿度

提前非常感谢

您不需要那么多绘图调用。你可以一次完成

>>> ax = df.plot.bar(x='mes', y=list(df.columns[1:6]))
>>> plt.show()
关于在每个条上显示值,你可以参考这篇文章,我已经解释了如何将文本添加到直方图的顶部。您也可以对条形图执行相同的操作


这里有一些代码,用于放置条形图,将月份名称放在中间

请注意,ylim的原始计算是错误的,它不应该是最大值的和,而是最大值的最大值。我还添加了一些列上方带有单位的文本。我试着找到一些合适的颜色:红黄色表示温度,蓝色表示雨水,蓝绿色表示湿度

将熊猫作为pd导入
将matplotlib.pyplot作为plt导入
将matplotlib.ticker导入为ticker
meteo=[“一月”,9.2,13.6,4.7,37,70],
[“二月”,9.9,14.3,5.4,35,70],
[“三月”,11.8,16.1,7.4,36,70],
[“四月”,13.7,18.0,9.4,40,69],
[“五月”,16.9、21.1、12.8、47、70],
[“六月”、20.9、24.9、16.8、30、68],
[“7月”,23.9,28.0,19.8,21,67],
[“8月”,24.4、28.5、20.2、62、68],
[“9月”,21.7,26.0,17.4,81,70],
[“10月”,17.8、22.1、13.5、91、73],
[“11月”,13.0,17.3,8.6,59,71],
[“12月”,10.0,14.3,5.7,40,69]]
df=pd.数据帧(meteo)
#重命名(列={0:“mes”,1:“临时媒体mes”,2:“临时媒体máxima media”,3:“临时媒体mínima media”,4:“媒体lluvias mensual”,5:“Humedad media rel”},inplace=True)
df.重命名(列={0:“月”,1:“月平均温度”,2:“月最高温度”,3:“月最低温度”,4:“月平均降雨量”,5:“月平均相对湿度”},就地=真)
#设置钢筋的位置和宽度
位置=列表(范围(长度(df)))
num_col=len(测向列)-1
宽度=0.95/num\u col
图,ax=plt.子批次(图尺寸=(16,10))
bar#u colors=[“#feb24c”、“#f03b20”、“#ffeda0”、“#43a2ca”、“#a8ddb5”]
条形标签=df.columns[1:]
对于枚举(zip(df.columns[1:],条形图颜色,条形图标签)中的i,(colname,color,lbl):
delta_p=0.125+宽度*i
plt.bar([p+增量p表示位置中的p],
df[colname],宽度,颜色=颜色,标签=lbl)
对于范围内的j(len(df)):
ax.注释(“°C”如果i<3 else“mm”如果i==3 else”%,
xy=(位置[j]+delta_p,df[colname][j]+1),
哈(中)
ax.set_ylabel('金额')
ax.设置标题(“温度、雨水和湿度”)
ax.set_xticks(位置)
def更新标记(x,位置):
返回df['月][pos]
ax.xaxis.set\u major\u格式化程序(ticker.NullFormatter())
ax.xaxis.set\u minor\u格式化程序(ticker.FuncFormatter(update\u ticks))
ax.xaxis.set_minor_定位器(ticker.FixedLocator([p+0.5表示位置中的p]))
对于ax.xaxis.get_minor_ticks()中的勾号:
勾选。勾选1行。设置标记大小(0)
勾选。勾选2行。设置标记大小(0)
勾选标签1.设置水平对齐(“中心”)
plt.xlim(最小位置、最大位置)+1)
plt.ylim([0,10+max([max(df[colname]),用于df.columns[1:]]中的colname]))
plt.legend()
plt.grid()
plt.show()

谢谢你的回答@JohanC。您的代码非常优雅。你知道有什么快速的方法来标注这些条上的测量单位吗?我努力使颜色更合适,并添加了一些单位。文本栏很窄。再次非常感谢@JohanC。我会好好研究你的代码,以了解如何执行所有这些过程!!非常感谢!!:)