猿问

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

我有一个形状像这样的数据框:


   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将股票行情和源列设置为行索引并使用unstack将它们推到列轴上,这似乎确实有效


df.set_index(['timestamp', 'ticker', 'source'])

    .unstack(level=[1,2])

    .swaplevel(0,1,axis=1)

    .swaplevel(1,2,axis=1)

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


              LSE     LSE      LSE      LSE ...

          PX_LAST PX_LAST PX_CLOSE PX_CLOSE ...

timestamp 

20180101       1        7        2       8  ...

20180102       4        8        5      11  ...

有没有更简洁的方法来做到这一点,这样我就可以获得我想要的格式?


回首忆惘然
浏览 202回答 3
3回答

临摹微笑

一种选择是melt,set_index和unstack: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_OPENtimestamp                                                  20180101         3       1       2        9       7       820180102         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_OPENtimestamp                                                  20180101         3       1       2        9       7       820180102         6       4       5       12      10      11

蓝山帝景

您的解决方案应该稍作更改 - 中的列顺序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_OPENtimestamp                                                  20180101         3       1       2        9       7       820180102         6       4       5       12      10      11

收到一只叮咚

我的提议是通过以下方式更改您的解决方案:第 1 步:df.set_index(['timestamp', 'ticker', 'source']).unstack([1, 2]),就像您所做的那样。它将列保留为以下形状:          PX_LAST     PX_OPEN     PX_CLOSEticker          A   B       A   B        A   Bsource        LSE LSE     LSE LSE      LSE LSE(并timestamp作为索引)。第 2 步:reorder_levels([1, 2, 0], axis=1),而不是您的 2 条 swaplevel说明。它将列保留为:ticker          A       B       A       B        A        Bsource        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                        Bsource        LSE                      LSE          PX_LAST PX_OPEN PX_CLOSE PX_LAST PX_OPEN PX_CLOSEtimestamp20180101        1       2        3       7       8        920180102        4       5        6      10      11       12
随时随地看视频慕课网APP

相关分类

Python
我要回答