如何使用pandas groupby对某些行进行降序排序,将某些行进行升序排序

时间:2018-06-06 22:51:49

标签: python pandas sorting dataframe pandas-groupby

我有一个像这样的DataFrame:

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"行在一起)然后,对于每种货币我想要"要求&# 34;按降序排序,我想要"出价"按升序排序。现在,如果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'

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

2 个答案:

答案 0 :(得分:3)

正在发生的事情是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

答案 1 :(得分:1)

您可以创建一个帮助列,以依赖于另一个列的升序或降序进行排序。

此处我们的帮助列在price时否定type == 'ask'。然后,当我们按升序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
相关问题