【问题标题】:Sorting by absolute value without changing the data按绝对值排序而不更改数据
【发布时间】:2015-08-09 18:19:09
【问题描述】:

我正在寻找一种简单的方法来按特定列的绝对值对 pandas 数据帧进行排序,但实际上不会更改数据帧中的值。类似于sorted(df, key=abs) 的东西。所以如果我有一个像这样的数据框:

    a   b
0   1   -3
1   2   5 
2   3   -1
3   4   2
4   5   -9

在“b”上排序时得到的排序数据如下所示:

    a   b
2   3   -1
3   4   2
0   1   -3
1   2   5 
4   5   -9

【问题讨论】:

    标签: python pandas sorting dataframe


    【解决方案1】:

    Pandas 的完美简单解决方案 > V_1.1.0:

    sort_values() function中使用参数key

    import pandas as pd
    ttt = pd.DataFrame({'A': ['a', 'b', 'c', 'd', 'e', 'f'], 'B': [-3, -2, -1, 0, 1, 2]})
    
    ttt.sort_values(by='B', key=abs)
    

    将产生:

        A   B
    3   d   0
    2   c   -1
    4   e   1
    1   b   -2
    5   f   2
    0   a   -3
    

    【讨论】:

    • 直到看到这个答案才注意到key kwarg!
    • ttt.sort_values(by='B', key=pd.Series.abs) 也可以使用,也许对旧版本的 Pandas 也有效?
    • @CactusPhilosopher:不确定旧版本,因为根据the dockey arg 是“1.1.0 版中的新参数”,released on July 28, 2020
    【解决方案2】:

    使用更惯用的 pandas:使用 argsort

    更简洁的方法是在绝对值上调用Series.argsort,然后索引:

    df.iloc[df['b'].abs().argsort()]
    
       a  b
    2  3 -1
    3  4  2
    0  1 -3
    1  2  5
    4  5 -9
    

    如果需要重置索引,使用Series.reset_index

    df.iloc[df['b'].abs().argsort()].reset_index(drop=True)
    
       a  b
    0  3 -1
    1  4  2
    2  1 -3
    3  2  5
    4  5 -9
    

    最后,由于argsort 没有ascending 参数来指定升序/降序,您需要取反df['b'].abs() 才能按降序排序。

    df.iloc[(-df['b'].abs()).argsort()]
    
       a  b
    4  5 -9
    1  2  5
    0  1 -3
    3  4  2
    2  3 -1
    

    您也可以使用 NumPy 执行此操作 - 使用 np.absndarray.argsort

    df.iloc[np.abs(df['b'].values).argsort()]
    
       a  b
    2  3 -1
    3  4  2
    0  1 -3
    1  2  5
    4  5 -9
    

    或者,对于降序顺序,

    df.iloc[(-np.abs(df['b'].values)).argsort()]
    
       a  b
    4  5 -9
    1  2  5
    0  1 -3
    3  4  2
    2  3 -1
    

    【讨论】:

      【解决方案3】:

      更新

      由于0.17.0 ordersort 已被弃用(感谢@Ruggero Turra),您现在可以使用sort_values 来实现此目的:

      In[16]:
      
      df.reindex(df.b.abs().sort_values().index)
      Out[16]: 
         a  b
      2  3 -1
      3  4  2
      0  1 -3
      1  2  5
      4  5 -9
      

      【讨论】:

      • 我很想看到一个可以跨多个索引执行此操作的版本,例如,如果 index1 可以是“水果”或“蔬菜”,而 index2 是任何水果或蔬菜,并且值是在该项目上花费的总金额,可以按食物类型(index1)成本的绝对值对数据框进行排序,然后然后,在内部,按每种水果或蔬菜的成本。
      • 只为所有在这里并首先搜索具有最大abs listet的值的人,将代码更改为:df.reindex(df.b.abs().sort_values(ascending=False).index)
      猜你喜欢
      • 2015-03-10
      • 1970-01-01
      • 1970-01-01
      • 2012-05-02
      • 1970-01-01
      • 2020-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多