【问题标题】:How to set and group pandas multi-level columns?如何设置和分组 pandas 多级列?
【发布时间】:2019-01-13 17:08:21
【问题描述】:

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

   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  ...

有没有更简洁的方法可以让我得到我想要的格式?

【问题讨论】:

    标签: python pandas dataframe pivot pivot-table


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      您的解决方案应该有所改变 - 在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
      

      【讨论】:

        【解决方案3】:

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

        第一步: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
        

        【讨论】:

          猜你喜欢
          • 2019-11-09
          • 1970-01-01
          • 2018-02-25
          • 2019-09-29
          • 1970-01-01
          • 2018-01-07
          • 1970-01-01
          • 1970-01-01
          • 2016-05-07
          相关资源
          最近更新 更多