【问题标题】:Sort by multiple columns in Pandas, but with 'na_position' for secondary sort在 Pandas 中按多列排序,但使用 'na_position' 进行二次排序
【发布时间】:2020-11-23 10:06:54
【问题描述】:

我有一个像这样的 Pandas DataFrame

df = pd.DataFrame(
 {
   'OrderID': ['o1','o2','o3','o4','o5'],
   'CustomerID': ['c1','c1','c2','c2','c3'],
   'CustomerRating': [5,1,3, NaN,NaN]
    
 }
)

我想先按 CustomerID 对它进行排序,然后按 CustomerRating 排序,这样客户评级中的 NaN 就会排在最后。我知道df.sort_values(na_position = 'last'),但这仅适用于主要排序。如何使其适用于二级排序?

所以就像我将升序参数指定为每个元素对应一个排序级别的列表一样,我需要类似的 na_position 参数, 所以是这样的:

df.sort_values(['CustomerID', 'CustomerRating', ascending = [False, False], na_position =['last', 'last']]

我该怎么做?

谢谢

【问题讨论】:

  • 请发布您的预期结果
  • 提到的链接将帮助您根据空值的计数对数据框进行排序,但如果您按标识符列(OrderID 和 CustomerID)排序,它会重新洗牌。如果订购不重要,这可能是最好的解决方案。

标签: python pandas sorting


【解决方案1】:

简单的 df.sort_values(['CustomerID','CustomerRating'])

【讨论】:

    【解决方案2】:

    从你必须到Specify list for multiple sort orders 的文档中。我的解释是,排序顺序必须是合乎逻辑的。此外,您不能将 na_position 指定为对应于没有“NaN”的列。

     print(df.sort_values(['CustomerID', 'CustomerRating'], ascending = [False, False], na_position ='first'))#Here, NaN is first because `c3` and `c2` appear on top
    
    
    
      OrderID CustomerID  CustomerRating
    4      o5         c3             NaN
    3      o4         c2             NaN
    2      o3         c2             3.0
    0      o1         c1             5.0
    1      o2         c1             1.0
    
    print(df.sort_values(['CustomerID', 'CustomerRating'], ascending = [True, True], na_position ='last'))# This is reversed again because the sort is logical
    
    
    
       OrderID CustomerID  CustomerRating
    1      o2         c1             1.0
    0      o1         c1             5.0
    2      o3         c2             3.0
    3      o4         c2             NaN
    4      o5         c3             NaN
    
    print(df.sort_values(['CustomerID', 'CustomerRating'], ascending = [False, True], na_position ='first'))
    
    
    
      OrderID CustomerID  CustomerRating
    4      o5         c3             NaN
    3      o4         c2             NaN
    2      o3         c2             3.0
    1      o2         c1             1.0
    0      o1         c1             5.0
    

    【讨论】:

    • 这行不通 - df = pd.DataFrame( { 'OrderID': ['o1','o2','o3','o4','o5'], 'CustomerID': ['c1','c1','c2','c2','c3'], 'CustomerRating': [np.nan,np.nan,3, 1, 2] } )
    • 让我们试试把CustomerRating,首先,print(df.sort_values(['CustomerRating', 'CustomerID'], ascending = [False, True], na_position ='last'))
    • 仍有可能失败的测试用例。
    【解决方案3】:

    以下代码将根据每行中存在的空值计数对行进行排序。

    df.iloc[df.isnull().sum(axis=1).mul(1).argsort()]
    

    替代解决方案

    以下代码适用于所有测试用例。 Null 值将始终出现在最后,同时按 OrderID 和 CustomerID 排序。

    null_df=df[df.isnull().any(axis=1)]
    all_df=df[~df.index.isin(null_df.index)]
    
    all_df.sort_values(['OrderID', 'CustomerID'], ascending = [True, True], inplace=True)
    null_df.sort_values(['OrderID', 'CustomerID'], ascending = [True, True], inplace=True)
    
    final_df=pd.concat([all_df, null_df]).reset_index(drop=True)
    

    【讨论】:

      猜你喜欢
      • 2021-03-27
      • 2016-05-09
      • 1970-01-01
      • 2017-02-01
      • 2015-10-04
      • 1970-01-01
      • 2021-11-21
      • 2017-04-28
      • 1970-01-01
      相关资源
      最近更新 更多