【问题标题】:Pandas DataFrame.unstack() Changes Order of Row and Column HeadersPandas DataFrame.unstack() 更改行和列标题的顺序
【发布时间】:2013-06-19 00:34:28
【问题描述】:

我遇到了以下对行标题和列标题进行排序的问题。

这里是如何重现这个:

X =pd.DataFrame(dict(x=np.random.normal(size=100), y=np.random.normal(size=100)))
A=pd.qcut(X['x'], [0,0.25,0.5,0.75,1.0]) #create a factor
B=pd.qcut(X['y'], [0,0.25,0.5,0.75,1.0]) # create another factor

g = X.groupby([A,B])['x'].mean() #do a two-way bucketing


print g 

#this gives the following and so far so good

x                 y               
[-2.315, -0.843]  [-2.58, -0.567]    -1.041167
                  (-0.567, 0.0321]   -1.722926
                  (0.0321, 0.724]    -1.245856
                  (0.724, 3.478]     -1.240876
(-0.843, -0.228]  [-2.58, -0.567]    -0.576264
                  (-0.567, 0.0321]   -0.501709
                  (0.0321, 0.724]    -0.522697
                  (0.724, 3.478]     -0.506259
(-0.228, 0.382]   [-2.58, -0.567]     0.175768
                  (-0.567, 0.0321]    0.214353
                  (0.0321, 0.724]     0.113650
                  (0.724, 3.478]     -0.013758
(0.382, 2.662]    [-2.58, -0.567]     0.983807
                  (-0.567, 0.0321]    1.214640
                  (0.0321, 0.724]     0.808608
                  (0.724, 3.478]      1.515334
Name: x, dtype: float64

#Now let's make a two way table and here is the problem:

HTML(g.unstack().to_html())

这表明:

y                 (-0.567, 0.0321]  (0.0321, 0.724]  (0.724, 3.478]  [-2.58, -0.567]
x                                                                                   
(-0.228, 0.382]           0.214353         0.113650       -0.013758         0.175768
(-0.843, -0.228]         -0.501709        -0.522697       -0.506259        -0.576264
(0.382, 2.662]            1.214640         0.808608        1.515334         0.983807
[-2.315, -0.843]         -1.722926        -1.245856       -1.240876        -1.041167

注意标题不再排序。我想知道什么是解决这个问题的好方法,从而使交互工作变得容易。

要进一步找出问题所在,请运行以下命令:

g.unstack().columns

它给了我这个: 索引([(-0.567, 0.0321], (0.0321, 0.724], (0.724, 3.478], [-2.58, -0.567]], dtype=object)

现在将其与 B.levels 进行比较:

B.levels
Index([[-2.58, -0.567], (-0.567, 0.0321], (0.0321, 0.724], (0.724, 3.478]], dtype=object)

原来Factor中的顺序显然丢失了。

现在更糟糕的是,我们来做一个多级交叉表:

g2 = X.groupby([A,B]).agg('mean')
g3 = g2.stack().unstack(-2)
HTML(g3.to_html())

它显示类似:

y                   (-0.567, 0.0321]  (0.0321, 0.724]  (0.724, 3.478]  
x                                                                       
(-0.228, 0.382]  x          0.214353         0.113650       -0.013758   
                 y         -0.293465         0.321836        1.180369   
(-0.843, -0.228] x         -0.501709        -0.522697       -0.506259   
                 y         -0.204811         0.324571        1.167005   
(0.382, 2.662]   x          1.214640         0.808608        1.515334   
                 y         -0.195446         0.161198        1.074532   
[-2.315, -0.843] x         -1.722926        -1.245856       -1.240876   
                 y         -0.392896         0.335471        1.730513  

行标签和列标签的排序都不正确。

谢谢。

【问题讨论】:

  • 这是一个很好的问题。奇怪的是,这些 bin 对象实际上只是字符串。

标签: python pandas


【解决方案1】:

这似乎有点小技巧,但这里是:

In [11]: g_unstacked = g.unstack()

In [12]: g_unstacked
Out[12]:
y                 (-0.565, 0.12]  (0.12, 0.791]  (0.791, 2.57]  [-2.177, -0.565]
x
(-0.068, 0.625]         0.389408       0.267252       0.283344          0.258337
(-0.892, -0.068]       -0.121413      -0.471889      -0.448977         -0.462180
(0.625, 1.639]          0.987372       1.006496       0.830710          1.202158
[-3.124, -0.892]       -1.513954      -1.482813      -1.394198         -1.756679

利用unique 保留顺序*的事实(从 g 的索引中获取唯一的第一项):

In [13]: g.index.get_level_values(0).unique()
Out[13]:
array(['[-3.124, -0.892]', '(-0.892, -0.068]', '(-0.068, 0.625]',
       '(0.625, 1.639]'], dtype=object)

如您所见,它们的顺序是正确的。

现在你可以通过这个reindex

In [14]: g_unstacked.reindex(g.index.get_level_values(0).unique())
Out[14]:
y                 (-0.565, 0.12]  (0.12, 0.791]  (0.791, 2.57]  [-2.177, -0.565]
[-3.124, -0.892]       -1.513954      -1.482813      -1.394198         -1.756679
(-0.892, -0.068]       -0.121413      -0.471889      -0.448977         -0.462180
(-0.068, 0.625]         0.389408       0.267252       0.283344          0.258337
(0.625, 1.639]          0.987372       1.006496       0.830710          1.202158

现在的顺序正确。

更新(我错过了列也不按顺序)。
您可以对列使用相同的技巧(您必须链接这些操作):

In [15]: g_unstacked.reindex_axis(g.index.get_level_values(1).unique(), axis=1)

* 这就是 Series unique 比 np.unique 快得多的原因。

【讨论】:

  • 这仅适用于行标题。列标题的顺序仍然错误。此外,输入 iPython 有点乏味。还有更简洁的方法吗?
  • 是的,这绝对是一个 hack...(哎呀,假设 cols 是有序的,可以对它们应用相同的 hack)。也许其他人会有更好的方法!
  • 如果行索引是MultiIndex,你知道如何重新索引吗?我编辑了我的问题,最后一部分显示了它是多级索引的情况。谢谢。
  • @TomBennett 老实说,将这部分作为一个新问题提出可能会更好(因为这部分已经非常涉及)......我认为更一般的问题可能很有趣,但我会快速思考。我今天发布了enhancement idea easrlier,这将使这变得非常容易!
猜你喜欢
  • 1970-01-01
  • 2022-01-07
  • 1970-01-01
  • 2021-01-14
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
  • 2019-10-04
  • 1970-01-01
相关资源
最近更新 更多