如何设置和分组熊猫多级列?

时间:2019-01-13 17:08:22

标签: python pandas dataframe pivot pivot-table

我的数据框的形状如下:

                                     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

我尝试首先使用unstack将行情指示器和源列设置为行索引,然后使用df.set_index(['timestamp', 'ticker', 'source']) .unstack(level=[1,2]) .swaplevel(0,1,axis=1) .swaplevel(1,2,axis=1) 将其推入似乎有效的列轴

              LSE     LSE      LSE      LSE ...
          PX_LAST PX_LAST PX_CLOSE PX_CLOSE ...
timestamp 
20180101       1        7        2       8  ...
20180102       4        8        5      11  ...

这可以解决问题,但是有两个问题:1)非常冗长,我们需要做所有的swaplevel调用来使列成为正确的形状。 2)似乎并没有按照我希望的方式进行分组,即我得到的结果是这样的:

# dmesg -T | egrep -i 'killed process'

是否有一种更清洁的方法来执行此操作,以便获得所需的格式?

3 个答案:

答案 0 :(得分:3)

一个选项是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

meltpivot_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

答案 1 :(得分:1)

您的解决方案应该有所更改-以set_index中的列顺序,省略第二个swaplevel并添加sort_index

df = (df.set_index(['timestamp', 'source', 'ticker'])
        .unstack(level=[1,2])
        .swaplevel(0,2,axis=1)
        .sort_index(axis=1)
)
print (df)
ticker           A                        B                
source         LSE                      LSE                
          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

答案 2 :(得分:0)

我的建议是通过以下方式更改您的解决方案:

步骤1:df.set_index(['timestamp', 'ticker', 'source']).unstack([1, 2]), 就像你一样。

它使列保持以下形状:

          PX_LAST     PX_OPEN     PX_CLOSE
ticker          A   B       A   B        A   B
source        LSE LSE     LSE LSE      LSE LSE

(和timestamp作为索引)。

第2步:reorder_levels([1, 2, 0], axis=1),而不是您的2 swaplevel指令。

它将列保留为:

ticker          A       B       A       B        A        B
source        LSE     LSE     LSE     LSE      LSE      LSE
          PX_LAST PX_LAST PX_OPEN PX_OPEN PX_CLOSE PX_CLOSE

最后一步是sort_index(axis=1, level=[0,1], sort_remaining=False)

请注意,您仅排序 级别0和1,因此顺序位于最后一级 保持不变(PX_LAST,PX_OPEN,PX_CLOSE)。

因此整个脚本(即一条指令)是:

df2 = df.set_index(['timestamp', 'ticker', 'source']).unstack([1, 2])\
    .reorder_levels([1, 2, 0], axis=1)\
    .sort_index(axis=1, level=[0,1], sort_remaining=False)

打印结果时,您将得到:

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