Pandas - 带有分组数据的条形图,按照其他列表中的数据对组进行排序

时间:2016-06-30 05:42:17

标签: sorting pandas matplotlib bar-chart

要求:

  • 我试图创建一个条形图,其中,对于每个条件("标签"),我显示每个操作的平均任务时间("模式")。因此,将有8组3个酒吧,一组有一个酒吧。
  • 我需要在每个栏上显示错误栏(标准错误)。
  • 我希望通过使用其他一些指标完成的某些计算来确定每个条件/标签的顺序。 (这些我已经从标签==>索引/订单中提取到dict映射中)
  • 我将绘制一些其他图表,并且其中使用的任何排序顺序也必须与其他图表相同
  • 这是Python 2.7,Pandas 0.18和IPython Notebook
  • (数据框从csv文件加载,而不是直接构建)

问题:

所以,这是图表目前的样子:

Current Graph

我已经替换/删除了要在此处上传的标签,但是,就像这些标签一样,原件按字母顺序排序。

其中存在的问题是:希望每种技术按字母顺序排序。相反,我希望它们可以根据我在一个单独的列表中排序的排序顺序进行排序(即,这样我就可以按顺序显示它们 - 最短到最高,同时保持相同跨图表订购。

当前代码:

因此,我从csv文件加载完整数据集:

p = pd.read_csv("...", sep='\t')

然后,我使用groupby来提取" task_time"绘制每个栏的数据:

tt_all = p.groupby(['label', 'pattern'])[['task_time']]

然后通过执行以下操作:

tt_all.mean().unstack().plot(kind='bar', yerr=tt_all.sem().unstack(), figsize=(15, 6), cmap=cmap, edgecolor='None', rot=45)

(没有unstack(),它只是将所有内容推到一个类别中并造成一团糟)

我尝试过的事情:

经过大量的探索之后,我设法得到了以下内容:

# Create a column to use for sorting things
sort_order_keys = {'I': 8, 'F': 3, 'H': 7, 'G': 1, 'D': 2, 'C': 5, 'E': 6, 'A': 4, 'B': 0}
p['label_sort_key'] = p['label'].apply(lambda x: sort_order_keys[x])  

# This sorts all the rows by the sort order
tt_all_raw = p.sort(['label_sort_key', 'pattern'])
tt_all_raw = tt_all_raw.iloc[tt_all_raw['label_sort_key'].argsort()]
print tt_all_raw     # <--- This will be sorted correctly

# Performing grouping....
tt_all = tt_all_raw.groupby(['label', 'pattern'], sort=False)[['task_time']]
print tt_all.mean()   # <---- This will also be sorted correctly

print tt_all.mean().unstack()  # <--- This however forces everything back to alphabetical order! Argh!

问题(S)

  • 如何重新排序unstack()结果? OR
  • 根据这些要求,是否有更简单的方法来设置这样的图形?

2 个答案:

答案 0 :(得分:0)

我认为您可以将CategoricalIndex与自定义订单的类别结合使用,可以按sort_index轻松排序:

print (p)
  label  pattern  task_time
0     I        0          3
1     E        0          0
2     B        1          2
3     D        1          1
4     G        1          0
5     F        0          3
6     H        0          0
7     D        1          2
8     A        1          1
9     C        1          0
tt_all = p.groupby(['label', 'pattern'])[['task_time']]
print (tt_all.mean())
               task_time
label pattern           
A     1              1.0
B     1              2.0
C     1              0.0
D     1              1.5
E     0              0.0
F     0              3.0
G     1              0.0
H     0              0.0
I     0              3.0

df1 = tt_all.mean().unstack()
df1.index = pd.CategoricalIndex(df1.index, 
                                categories=['B', 'G', 'D', 'F', 'A', 'C', 'E', 'H', 'I'], 
                                ordered=True)
df1.sort_index(inplace=True)
print (df1)
        task_time     
pattern         0    1
B             NaN  2.0
G             NaN  0.0
D             NaN  1.5
F             3.0  NaN
A             NaN  1.0
C             NaN  0.0
E             0.0  NaN
H             0.0  NaN
I             3.0  NaN

答案 1 :(得分:0)

我遇到了同样的问题,我通过将GroupBy object变为DataFrame并将有序类别作为列表传递给index参数来绕过此问题。

这对你有用吗?

sort_order_keys = ['B', 'G', 'D', 'F', 'A', 'C', 'E', 'H', 'I']
tt_all = pandas.DataFrame(tt_all, index = sort_order_keys)

然后,您应该能够在数据帧上使用绘图功能。

在组上使用.count()方法时,我发现在将GroupBy object传递给dict()函数之前将pandas.DataFrame()转换为字典非常有用并使用组标签作为列的标签,并将index命名为&#39; count&#39;,例如:

tt_allCount = pandas.DataFrame(dict(tt_all.count()), 
                                    columns = sort_order_keys,
                                    index=['count'])