Seaborn 条形图排序

41
我有一个带有两列的pandas数据框。 需要按“Count”列排序后进行绘图。
dicti=({'37':99943,'25':47228,'36':16933,'40':14996,'35':11791,'34':8030,'24' : 6319 ,'2'  :5055 ,'39' :4758 ,'38' :4611  })
pd_df = pd.DataFrame(list(dicti.iteritems()))
pd_df.columns =["Dim","Count"]
plt.figure(figsize=(12,8))
ax = sns.barplot(x="Dim", y= "Count",data=pd_df )
ax.get_yaxis().set_major_formatter(plt.FuncFormatter(lambda x, loc: "
{:,}".format(int(x))))
ax.set(xlabel="Dim", ylabel='Count')
for item in ax.get_xticklabels():
    item.set_rotation(90)
for i, v in enumerate(pd_df["Count"].iteritems()):        
    ax.text(i ,v[1], "{:,}".format(v[1]), color='m', va ='bottom', 
    rotation=45)
plt.tight_layout()

当前情况下,图表被“Dim”列排序,我需要按“Count”列排序。如何实现?enter image description here


1
你看过 barplot 的文档了吗?它有一个叫做 order 的参数。这个参数可以按照你的 Count 列进行排序,然后传递结果为 Dim 值。 - Paul H
6个回答

58

您可以使用order参数来实现此操作。

sns.barplot(x='Id', y="Speed", data=df, order=result['Id'])

感谢Wayne提供的代码。

查看他的其他代码

对我来说,这个链接仍然有效。但为了方便起见,我在此粘贴了作者的代码。

result = df.groupby(["Id"])['Speed'].aggregate(np.median).reset_index().sort_values('Speed')
sns.barplot(x='Id', y="Speed", data=df, order=result['Id'])
plt.show()

df

   Id  Speed
0   1     30
1   1     35
2   1     31
3   2     20
4   2     25

结果

   Id   Speed
1   2   22.5
0   1   31.0
2   3   80.0

3
可以按照估计值排序吗?sns.barplot(x='Id', y="Speed", data=df, estimator=np.mean, order=?) - vladkras
1
可能有更好的方法,但这个也可以:grp_order = df.groupby('Id').Speed.agg('mean').sort_values().index 然后 sns.barplot(x='Id', y="Speed", data=df, estimator=np.mean, order=grp_order) - Jeremy
1
我无法让它工作,链接也没有显示任何与您的解决方案相关的内容。result应该是什么或返回什么?返回一个整数的字典?这给了我一个错误。 - CGFoX
2
最好您展示一下如何计算result。目前的情况是,您只提供了一个不起作用的代码行。 - SO_tourist

20
你需要按照所需的方式对数据框进行排序,然后重新索引它以创建升序/降序索引。之后,你可以绘制以索引为x值的条形图。接下来,通过数据框的Dim列设置标签。
import matplotlib.pylab as plt
import pandas as pd
import seaborn as sns

dicti=({'37':99943,'25':47228,'36':16933,'40':14996,'35':11791,'34':8030,'24' : 6319 ,'2'  :5055 ,'39' :4758 ,'38' :4611  })
pd_df = pd.DataFrame(list(dicti.items()))
pd_df.columns =["Dim","Count"]
print (pd_df)
# sort df by Count column
pd_df = pd_df.sort_values(['Count']).reset_index(drop=True)
print (pd_df)

plt.figure(figsize=(12,8))
# plot barh chart with index as x values
ax = sns.barplot(pd_df.index, pd_df.Count)
ax.get_yaxis().set_major_formatter(plt.FuncFormatter(lambda x, loc: "{:,}".format(int(x))))
ax.set(xlabel="Dim", ylabel='Count')
# add proper Dim values as x labels
ax.set_xticklabels(pd_df.Dim)
for item in ax.get_xticklabels(): item.set_rotation(90)
for i, v in enumerate(pd_df["Count"].iteritems()):        
    ax.text(i ,v[1], "{:,}".format(v[1]), color='m', va ='bottom', rotation=45)
plt.tight_layout()
plt.show()

在此输入图片描述


2
我是否理解正确 -- 即使我已经对数据框进行了排序,我仍然需要首先使用索引作为标签创建它,以确保sns不会根据标签名称按字母顺序对条形图进行排序(并且没有办法传递例如 sorted = False 来避免这种情况)? - Rotkiv

11

准备数据框,使其按照您想要的列排序。

现在将其作为参数传递给函数。

import pandas as pd
import seaborn as sns

dicti=({'37': 99943,'25': 47228,'36': 16933,'40': 14996,'35': 11791,'34': 8030,'24': 6319 ,'2': 5055 ,'39': 4758 ,'38' :4611})
pd_df = pd.DataFrame(list(dicti.items()))
pd_df.columns =["Dim", "Count"]

# Here the dataframe is already sorted if not use the below line
# pd_df = pd_df.sort_values('Count').reset_index()
# or 
# pd_df = pd_df.sort_values('Count',ascending=False).reset_index()

sns.barplot(x='Dim', y='Count', data=pd_df, order=pd_df['Dim'])`

在这里输入图片描述


9
为了制定特定订单,我建议创建一个列表,然后按照该列表排序:
order_list = ['first', 'second', 'third']
sns.barplot(x=df['x'], y=df['y'], order=order_list)

2

尝试使用这个。无需对数据帧进行排序或创建额外的列表。

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

dicti=({'34':8030,'37':99943,'38':4611,'25':47228,'39':4758,'36':16933,'2':5055,'40':14996,'24':6319,'35':11791})
pd_df = pd.DataFrame(list(dicti.items()))
pd_df.columns =["Dim","Count"]
plt.figure(figsize=(12,8))
ax = sns.barplot(x="Dim", y= "Count",data=pd_df, order=pd_df.sort_values(by=['Count'], ascending=False).set_index('Dim').index)
ax.get_yaxis().set_major_formatter(plt.FuncFormatter(lambda x, loc: "{:,}".format(int(x))))
ax.set(xlabel="Dim", ylabel='Count')
for item in ax.get_xticklabels():
    item.set_rotation(90)
#for i, v in enumerate(pd_df["Count"].iteritems()):        
#    ax.text(i ,v[1], "{:,}".format(v[1]), color='m', va ='bottom', 
#    rotation=45)
plt.tight_layout()

output

注意:您可能会注意到有3行代码被转换为注释。这是因为@Tronald Dump特别询问了Seaborn Bar Plot功能,但存在用于显示自定义品红标签的代码,该代码不考虑seaborn.barplot函数的可选“order”参数的使用。因此,这是对OP的有效答案,但特别适用于未来的访问者。

1
您可以使用以下代码。
import seaborn as sns

iris = sns.load_dataset("iris")
order = iris.groupby(["species"])["sepal_width"].mean().sort_values().index

sns.barplot(x="species", y="sepal_width", data=iris, order=order)

enter image description here

如果您想将它们从大到小排序,可以指定 ascending=False
order = iris.groupby(["species"])["sepal_width"].mean().sort_values(ascending=False).index

这对于那些不想按绝对值排序,而是按像平均值这样的统计量排序的情况非常有用!超级实用! - Mitchell van Zuylen

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