我想根据多列对 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 列进行排序,其中在 col2
和 col3
中用于比较我想要使用的两个元素的函数是我自定义的函数。 (对于 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 列进行排序。
答案 0 :(得分:1)
您的关键功能需要将整个系列作为输入。
像这样重写你的函数:
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)