piR*_*red 2 python sorting numpy pandas
我已经以不同的背景为幌子多次回答了这个问题,并且我意识到在任何地方都没有一种好的规范方法。
因此,要设置一个简单的问题:
df = pd.DataFrame(dict(A=range(6), B=[1, 2] * 3))
print(df)
A B
0 0 1
1 1 2
2 2 1
3 3 2
4 4 1
5 5 2
Run Code Online (Sandbox Code Playgroud)
如何按“ A'和”列的乘积排序'B'?
这是一种将临时列添加到数据框,sort_values然后使用drop它的方法。
df.assign(P=df.prod(1)).sort_values('P').drop('P', 1)
A B
0 0 1
1 1 2
2 2 1
4 4 1
3 3 2
5 5 2
Run Code Online (Sandbox Code Playgroud)
有没有更好,更简洁,更清晰,更一致的方法?
TL; DR
iloc +argsort
我们可以使用以下iloc顺序来实现此目的:我们可以使用一系列顺序位置并返回按这些位置重新排序的数据框。
利用的能力iloc,我们可以sort使用任何指定顺序的数组。
现在,我们要做的就是确定一种获得此排序的方法。原来有一个叫做的方法argsort可以做到这一点。通过将的结果传递argsort给iloc,我们可以整理出数据框。
使用上面指定的问题
df.iloc[df.prod(1).argsort()]
Run Code Online (Sandbox Code Playgroud)
与上述结果相同
A B
0 0 1
1 1 2
2 2 1
4 4 1
3 3 2
5 5 2
Run Code Online (Sandbox Code Playgroud)
为了简单起见。如果性能成为问题,我们可以采取进一步措施,并专注于numpy
v = df.values
a = v.prod(1).argsort()
pd.DataFrame(v[a], df.index[a], df.columns)
Run Code Online (Sandbox Code Playgroud)
这些解决方案有多快?
我们可以看到,这pd_ext_sort是最简洁的方法,但是缩放性却不如其他方法。
np_ext_sort以透明度为代价提供最佳性能。不过,我认为目前还很清楚。
回测设置
def add_drop():
return df.assign(P=df.prod(1)).sort_values('P').drop('P', 1)
def pd_ext_sort():
return df.iloc[df.prod(1).argsort()]
def np_ext_sort():
v = df.values
a = v.prod(1).argsort()
return pd.DataFrame(v[a], df.index[a], df.columns)
results = pd.DataFrame(
index=pd.Index([10, 100, 1000, 10000], name='Size'),
columns=pd.Index(['add_drop', 'pd_ext_sort', 'np_ext_sort'], name='method')
)
for i in results.index:
df = pd.DataFrame(np.random.rand(i, 2), columns=['A', 'B'])
for j in results.columns:
stmt = '{}()'.format(j)
setup = 'from __main__ import df, {}'.format(j)
results.set_value(i, j, timeit(stmt, setup, number=100))
results.plot()
Run Code Online (Sandbox Code Playgroud)
假设我有一列负值和正值。我想通过增加幅度进行排序...但是,我希望负面因素排在第一位。
假设我有数据框 df
df = pd.DataFrame(dict(A=range(-2, 3)))
print(df)
A
0 -2
1 -1
2 0
3 1
4 2
Run Code Online (Sandbox Code Playgroud)
我将再次设置3个版本。这次,我将使用np.lexsort返回与相同类型的数组argsort。意思是,我可以用它来重新排序数据框。
警告:首先 np.lexsort按列表中的最后一个数组排序。 \ shurg
def add_drop():
return df.assign(P=df.A >= 0, M=df.A.abs()).sort_values(['P', 'M']).drop(['P', 'M'], 1)
def pd_ext_sort():
v = df.A.values
return df.iloc[np.lexsort([np.abs(v), v >= 0])]
def np_ext_sort():
v = df.A.values
a = np.lexsort([np.abs(v), v >= 0])
return pd.DataFrame(v[a, None], df.index[a], df.columns)
Run Code Online (Sandbox Code Playgroud)
全部返回
A
1 -1
0 -2
2 0
3 1
4 2
Run Code Online (Sandbox Code Playgroud)
这次有多快?
在此示例中,pd_ext_sort和均np_ext_sort胜过add_drop。
回测设置
results = pd.DataFrame(
index=pd.Index([10, 100, 1000, 10000], name='Size'),
columns=pd.Index(['add_drop', 'pd_ext_sort', 'np_ext_sort'], name='method')
)
for i in results.index:
df = pd.DataFrame(np.random.randn(i, 1), columns=['A'])
for j in results.columns:
stmt = '{}()'.format(j)
setup = 'from __main__ import df, {}'.format(j)
results.set_value(i, j, timeit(stmt, setup, number=100))
results.plot(figsize=(15, 6))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
978 次 |
| 最近记录: |