如何用Seaborn绘制以列名为分组元素的分组条形图?
问题:Seaborn绘制分组条形图是否需要转换数据?
我不确定能不能直接用Seaborn实现分组条形图(或catplot),核心需求是分组元素对应数据框的列名而非值。
给出的数据如下:
Year Gin Beer 0 2016 84 78 1 2017 75 30 2 2018 42 47 3 2019 25 58 4 2020 51 90 5 2021 40 50
期望的图表样式是按年份分组,每个年份对应Gin和Beer两个条形的分组条形图。
我尝试了以下代码,在y=参数中直接指定列名:
sns.catplot(data=a, x='Year', y=['Gin', 'Beer'])
请问是否无需修改数据就能实现该需求,还是必须对数据进行转换?
以下是最小可复现代码:
#!/usr/bin/env python3 import random as rd import pandas as pd from matplotlib import pyplot as plt import seaborn as sns sns.set_theme() rd.seed(0) a = pd.DataFrame({ 'Year': [2016, 2017, 2018, 2019, 2020, 2021], 'Gin': rd.choices(range(100), k=6), 'Beer': rd.choices(range(100), k=6) }) print(a) # sns.catplot(data=a, x='Year', y=['Gin', 'Beer']) # plt.show()
解答
必须先转换数据,Seaborn的catplot(包括条形图类型)要求数据是长格式(long-form),而你当前的数据是宽格式(wide-form),直接传入多列作为y轴参数会报错。
你可以用pandas的melt方法快速转换数据格式:
# 将宽格式数据转换为长格式 df_long = a.melt(id_vars='Year', var_name='Drink', value_name='Amount') # 绘制分组条形图 sns.catplot(data=df_long, x='Year', y='Amount', hue='Drink', kind='bar') plt.show()
说明:
melt方法保留Year作为标识列,把Gin、Beer这类列名转换为Drink列的分类值,对应的数据值存入Amount列。- 转换后通过
hue='Drink'参数区分不同饮品,就能实现你需要的分组条形图效果。
如果不想转换数据,只能用matplotlib的原生bar函数手动计算条形位置来绘制,但Seaborn的catplot系列函数不支持直接处理宽格式数据,这是由它的设计逻辑决定的。
内容的提问来源于stack exchange,提问作者buhtz
相关产品推荐
相关产品推荐

