【问题标题】:How to use pandas groupby to sort some rows descending and some rows ascending如何使用pandas groupby对一些行降序和一些行升序排序
【发布时间】:2018-11-16 17:56:28
【问题描述】:

我有一个这样的数据框:

import pandas as pd
df = pd.DataFrame(
    [
              ["EUR"          , 0.031        , 61.170000 , "ask" ],
              ["EUR"          , 7.642        , 61.360000 , "ask" ],
              ["EUR"          , 0.266        , 61.370000 , "ask" ],
              ["EUR"          , 0.364        , 61.410000 , "ask" ],
              ["EUR"          , 0.101        , 61.100000 , "bid" ],
              ["EUR"          , 23.090       , 60.470000 , "bid" ],
              ["EUR"          , 2.061        , 60.460000 , "bid" ],
              ["EUR"          , 0.133        , 60.450000 , "bid" ],
              ["USD"          , 3.031        , 161.170000, "ask" ],
              ["USD"          , 10.642       , 161.360000, "ask" ],
              ["USD"          , 3.266        , 161.370000, "ask" ],
              ["USD"          , 3.364        , 161.410000, "ask" ],
              ["USD"          , 3.101        , 161.100000, "bid" ],
              ["USD"          , 26.090       , 160.470000, "bid" ],
              ["USD"          , 5.061        , 160.460000, "bid" ],
              ["USD"          , 3.133        , 160.450000, "bid" ],
    ],
    columns = ["base_currency", "base_volume", "price"  , "type"]
)
df

我想对行重新排序。具体来说,我想将货币(所有“EUR”行放在一起,所有“USD”行放在一起)然后,对于每种货币,我希望“询问”按降序排序,并且我希望“出价”为升序排列。现在,如果 DataFrame 仅包含一种货币,我可以通过以下方式正常工作:

_df = df.groupby("type").apply(lambda row: row.sort_values(by = "price"))
_df

我必须处理多种货币,但是当我尝试按以下方式对它们进行分组时

_df = df.groupby(["base_currency", "type"]).apply(
    lambda row:
        row.sort_values(by = "price") if row['type'] == 'ask' else\
        row.sort_values(by = "price", ascending = False),
    axis = 1
)
_df

我收到以下错误:

TypeError: <lambda>() got an unexpected keyword argument 'axis'

这里可能发生了什么?我该如何解决?

【问题讨论】:

    标签: python pandas sorting dataframe pandas-groupby


    【解决方案1】:

    发生的情况是 groupby.apply 没有错误提示的 axis 参数,您可以这样做:

    df.groupby(
        ['base_currency', 'type'], group_keys=False
    ).apply(
        lambda g: g.sort_values('price', ascending=g.name[1] == 'bid')     
        # check the type for each group and sort accordingly
    )
    
    #   base_currency  base_volume   price type
    #3            EUR        0.364   61.41  ask
    #2            EUR        0.266   61.37  ask
    #1            EUR        7.642   61.36  ask
    #0            EUR        0.031   61.17  ask
    #7            EUR        0.133   60.45  bid
    #6            EUR        2.061   60.46  bid
    #5            EUR       23.090   60.47  bid
    #4            EUR        0.101   61.10  bid
    #11           USD        3.364  161.41  ask
    #10           USD        3.266  161.37  ask
    #9            USD       10.642  161.36  ask
    #8            USD        3.031  161.17  ask
    #15           USD        3.133  160.45  bid
    #14           USD        5.061  160.46  bid
    #13           USD       26.090  160.47  bid
    #12           USD        3.101  161.10  bid
    

    【讨论】:

      【解决方案2】:

      您可以创建一个辅助列以根据另一个列进行升序或降序排序。

      这里我们的辅助列在type == 'ask' 时否定price。然后,当我们按升序sort_values 的默认值)排序时,我们会得到预期的结果,即按降序对这些行进行排序price

      import numpy as np
      
      df['price_helper'] = df['price'] * np.where(df['type'] == 'ask', -1, 1)
      
      df_sorted = df.sort_values(['base_currency', 'type', 'price_helper'])\
                    .drop('price_helper', 1)
      
      print(df_sorted)
      
         base_currency  base_volume   price type
      3            EUR        0.364   61.41  ask
      2            EUR        0.266   61.37  ask
      1            EUR        7.642   61.36  ask
      0            EUR        0.031   61.17  ask
      7            EUR        0.133   60.45  bid
      6            EUR        2.061   60.46  bid
      5            EUR       23.090   60.47  bid
      4            EUR        0.101   61.10  bid
      11           USD        3.364  161.41  ask
      10           USD        3.266  161.37  ask
      9            USD       10.642  161.36  ask
      8            USD        3.031  161.17  ask
      15           USD        3.133  160.45  bid
      14           USD        5.061  160.46  bid
      13           USD       26.090  160.47  bid
      12           USD        3.101  161.10  bid
      

      性能

      基于lambda 的方法和“帮助列”方法的性能相似。在我看来,选择你认为可维护的。

      def psi(df):
          return df.groupby(['base_currency', 'type'], group_keys=False)\
                   .apply(lambda g: g.sort_values('price', ascending=g.name[1] == 'bid'))
      
      def jp(df):
          df['price_helper'] = df['price'] * np.where(df['type'] == 'ask', -1, 1)
          return df.sort_values(['base_currency', 'type', 'price_helper'])\
                   .drop('price_helper', 1)
      
      data = pd.concat([data]*100000, ignore_index=True)
      
      %timeit psi(data)  # 969 ms
      %timeit jp(data)   # 899 ms
      

      【讨论】:

        猜你喜欢
        • 2021-10-25
        • 2022-11-26
        • 1970-01-01
        • 2015-01-17
        • 2020-06-06
        • 2020-11-09
        • 2016-11-05
        • 2021-08-24
        • 1970-01-01
        相关资源
        最近更新 更多