熊猫排序lambda函数



给定一个数据框a,有3列,A, B, C和3行数值。如何使用comp运算符仅使用A[i]*B[i]的乘积对所有行进行排序?似乎pandas只接受列,然后是排序方法。
我想使用下面的比较函数。

f = lambda i,j: a['A'][i]*a['B'][i] < a['A'][j]*a['B'][j]

至少有两种方法:

方法1

开头
In [175]: df = pd.DataFrame({'A': [1, 2], 'B': [1, -1], 'C': [1, 1]})

你可以添加一个列作为你的排序键

In [176]: df['sort_val'] = df.A * df.B

最后按它排序并删除它

In [190]: df.sort_values('sort_val').drop('sort_val', 1)
Out[190]: 
   A  B  C
1  2 -1  1
0  1  1  1

方法2

使用numpy.argsort,然后在生成的索引上使用.ix:

In [197]: import numpy as np
In [198]: df.ix[np.argsort(df.A * df.B).values]
Out[198]: 
   A  B  C
0  1  1  1
1  2 -1  1

另一种方法,在这里添加因为这是Google的第一个结果:

df.loc[(df.A * df.B).sort_values().index]

这对我来说很好,而且非常简单。@Ami Tavory的回答给了我一个分类索引的奇怪结果;我不确定是因为这个原因

只是添加了@srs 超级优雅的回答 iloc 选项,并与loc和朴素的解决方案进行了一些时间比较。

(当您的索引是基于位置的(而不是基于标签的loc)

import numpy as np
import pandas as pd
N = 10000
df = pd.DataFrame({
                   'A': np.random.randint(low=1, high=N, size=N), 
                   'B': np.random.randint(low=1, high=N, size=N)
                  })
%%timeit -n 100
df['C'] = df['A'] * df['B']
df.sort_values(by='C')

naive: 100循环,最佳3:1.85 ms/循环

%%timeit -n 100
df.loc[(df.A * df.B).sort_values().index]

loc: 100个循环,最好的3:2.69 ms每循环

%%timeit -n 100
df.iloc[(df.A * df.B).sort_values().index]

iloc: 100个循环,最好的3:2.02 ms每循环

df['C'] = df['A'] * df['B']
df1 = df.sort_values(by='C')
df2 = df.loc[(df.A * df.B).sort_values().index]
df3 = df.iloc[(df.A * df.B).sort_values().index]
print np.array_equal(df1.index, df2.index)
print np.array_equal(df2.index, df3.index)

所有选项之间的测试结果(比较整个索引顺序):

真正

真正

最新更新