我有一个数据框的形状如下:

   PX_LAST PX_OPEN PX_CLOSE ticker source timestamp
0        1       2        3      A   LSE   20180101
1        4       5        6      A   LSE   20180102
1        7       8        9      B   LSE   20180101
1       10      11       12      B   LSE   20180102
....

我想按以下格式按摩:
                                     A                          B
                                   LSE                        LSE
            PX_LAST, PX_CLOSE, PX_OPEN PX_LAST, PX_CLOSE, PX_OPEN
timestamp
20180101          1         2       3        7         8        9
20180102          4         5       6       10        11       12
....

我试图首先使用set_index将TIKER和Struts列设置为行索引,并使用unstack将它们推到列轴上,这看起来确实有效。
df.set_index(['timestamp', 'ticker', 'source'])
    .unstack(level=[1,2])
    .swaplevel(0,1,axis=1)
    .swaplevel(1,2,axis=1)

这样做的诀窍,但有两个问题:1)它是非常冗长的,与所有的swaplevel调用,我们需要做的,使列进入正确的形状。2)它似乎不做我希望它做的分组,即我得到的结果如下:
              LSE     LSE      LSE      LSE ...
          PX_LAST PX_LAST PX_CLOSE PX_CLOSE ...
timestamp
20180101       1        7        2       8  ...
20180102       4        8        5      11  ...

有没有一种更干净的方法可以让我得到我想要的格式?

最佳答案

一个选项是meltset_indexunstack

u = df.melt(['ticker', 'source', 'timestamp'])
(u.set_index(u.columns.difference({'value'}).tolist())['value']
  .unstack([1, 0, -1])
  .sort_index(axis=1))

ticker           A                        B
source         LSE                      LSE
variable  PX_CLOSE PX_LAST PX_OPEN PX_CLOSE PX_LAST PX_OPEN
timestamp
20180101         3       1       2        9       7       8
20180102         6       4       5       12      10      11

melt,和pivot_table
u = df.melt(['ticker', 'source', 'timestamp'])
u.pivot_table(index='timestamp',
              columns=['ticker','source','variable'],
              values='value')

ticker           A                        B
source         LSE                      LSE
variable  PX_CLOSE PX_LAST PX_OPEN PX_CLOSE PX_LAST PX_OPEN
timestamp
20180101         3       1       2        9       7       8
20180102         6       4       5       12      10      11

10-08 01:00