Python 使用自定义比较函数按多列对数据帧进行排序

Python 使用自定义比较函数按多列对数据帧进行排序,python,pandas,dataframe,Python,Pandas,Dataframe,我想根据多列对数据框进行排序,其中对于某些列(“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

我想根据多列对数据框进行排序,其中对于某些列(“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比较fn(l1,l2):#列表1和列表2
如果len(l1)len(l2):
返回1#l2的值小于l1
其他:
对于范围内的i(len(l1)):
如果l1[i]l2[i]:
返回1
返回0#l1和l2具有相同的值
现在,我想对所有3列进行排序,其中在
col2
col3
中,用于比较我想要使用的两个元素的函数是我的自定义函数。(对于col1来说,这是一种简单的排序)

我试过:

df.sort\u值([“col1”、“col2”、“col3”],key=[None,compare\u fn,compare\u fn])
,这将返回一个
“list”对象不可调用的
错误

从functools导入cmp\u到\u键;df.sort_值([“col1”、“col2”、“col3”],key=[None,cmp_to_key(compare_fn),cmp_to_key(compare_fn)])
,返回一个
“list”对象不可调用的
错误

我甚至尝试忽略第一列,将一个参数传递给键:
df[[“col2”,“col3”]]。排序_值([“col2”,“col3”],key=cmp_to_key(compare_fn))
返回
TypeError:functools.KeyWrapper类型的对象没有len()

df[[“col2”,“col3”]]。排序_值([“col2”,“col3”],key=compare\u fn)
返回
TypeError:compare\u fn()缺少1个必需的位置参数:“l2”


因此,我知道我的问题中至少有一个是不知道如何使用双元素比较函数对pandas DataFrame列进行排序。

您的关键函数需要将整个系列作为输入

按如下方式重写函数:

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)

明亮的对sort_values函数的多次调用处理了在选择列上应用基于自定义的排序的问题,将2-elemnt compare函数重新构造为键函数似乎就是这样工作的。我会做更多的测试来确认。我不知道python对元组的排序是这样的。@ZaidGharaybeh还看到了另一个版本函数的更新答案。
[ins]In[63]:y Out[63]:[1,2,3,4],[10,10],[1],[2],[3],[300000],[300000],[300000],[100],[1,100],[1,2],[nav]In[64]:排序(比较[64]:[0,(),[1,(1,(1,)),[64],[1],[1],],(1,(2,),(1,(3,),(1,(300000,),(1,(300000,),(1,(300000,),(2,(1,2)),(2,(10,10)),(2,(100,1)),(4,(1,2,3,4))。
我定义了一个列表
y
并对其应用了您的函数,它似乎工作得很好。很抱歉代码有误,但注释不能有适当的间距。
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)