首页 > 解决方案 > 使用自定义比较函数按多列对熊猫数据框进行排序

问题描述

我想针对多个列对 pandas 数据框进行排序,对于某些列(“col2”和“col3”),我想使用这个自定义的比较函数,它需要两个元素:

例子:

>>> df = pd.DataFrame({"col1": [1,2,3], "col2": [[2], [], [1]], "col3": [[1,0,1], [2,2,2], [3]]})

>>> df
   col1 col2       col3
0     1  [2]  [1, 0, 1]
1     2   []  [2, 2, 2]
2     3  [1]        [3]
def compare_fn(l1, l2): #list 1 and list 2 
    if len(l1) < len(l2):
        return -1 # l1 is of smaller value than l2
    if len(l1) > len(l2):
        return 1 # l2 is of smaller value than l1
    else:
        for i in range(len(l1)):
            if l1[i] < l2[i]:
                return -1
            elif l1[i] > l2[i]:
                return 1
    return 0 # l1 and l2 have same value

现在,我想对所有 3 列进行排序,其中用于比较我想要使用的两个元素col2col3函数是我的自定义函数。(对于 col1,这是一个简单的排序)。

我试过了:

df.sort_values(["col1", "col2", "col3"], key=[None, compare_fn, compare_fn]),这将返回一个'list' object is not callable错误。

from functools import cmp_to_key; df.sort_values(["col1", "col2", "col3"], key=[None, cmp_to_key(compare_fn), cmp_to_key(compare_fn)]),这将返回一个'list' object is not callable错误。

我什至尝试忽略第一列并将一个参数传递给键: df[["col2", "col3"]].sort_values(["col2", "col3"], key=cmp_to_key(compare_fn))返回TypeError: object of type 'functools.KeyWrapper' has no len()

df[["col2", "col3"]].sort_values(["col2", "col3"], key=compare_fn)返回TypeError: compare_fn() missing 1 required positional argument: 'l2'

所以我知道至少我的一个问题是不知道如何使用二元素比较函数对 pandas DataFrame 列进行排序。

标签: pythonpandasdataframe

解决方案


您的关键功能需要将整个系列作为输入。

像这样重写你的函数:

def compare_fn(l): #list 1 and list 2 
    return [(len(x), tuple(x)) for x in l]

(df.sort_values('col1')
   .sort_values(['col2','col3'], 
                key=compare_fn, kind='mergesort')
)

输出:

   col1 col2       col3
1     2   []  [2, 2, 2]
2     3  [1]        [3]
0     1  [2]  [1, 0, 1]

更新我们还可以重写该函数,使其适用于其他列:

def compare_fn(l): #list 1 and list 2 
    return ([(len(x), tuple(x)) for x in l]
                if type(l[0]) == list       # case list
                else l                      # case integer
           )

df.sort_values(['col1','col2','col3'], key=compare_fn)

推荐阅读