假设有一个包含3列数值的数据框a
,列名分别是A
、B
和C
,有三行数值。如何使用A[i]*B[i]
的乘积运算符对所有行进行排序?似乎pandas.sort只能对列进行排序并选择排序方法。
我想使用下面的比较函数。
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
方法二
使用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的答案在使用分类索引时给了我奇怪的结果; 不确定是不是因为那个原因。
df.**iloc**[(df.A * df.B).sort_values().index]
。 - morkiloc
选项进行一些时间比较,与loc
和朴素解决方案相比较更好(当您的索引是基于位置而非基于标签时,建议使用iloc)。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 loops, best of 3: 1.85 ms per loop
%%timeit -n 100
df.loc[(df.A * df.B).sort_values().index]
loc: 100次循环,3次中最好的结果:每次循环2.69毫秒
%%timeit -n 100
df.iloc[(df.A * df.B).sort_values().index]
iloc: 100 loops, best of 3: 2.02 ms per loop
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)
比较所有选项之间的测试结果(比较整个索引顺序):
最初的回答
最初的回答
df.assign(sortval = df.A * df.B).sort_values('sortval').drop('sortval', 1)
。 - kputnam