tar*_*ras 3 python sorting algorithm numpy pandas
我有一堆结构如下的数据框
df = pd.DataFrame(
[[1, 'A', 10], [2, 'A', 20], [3, 'A', 30],
[1, 'B', 20], [2, 'B', 20], [3, 'B', 10],
[1, 'M', 20], [2, 'M', 30], [3, 'M', 30]],
columns=['foo', 'bar', 'buzz']
)
Run Code Online (Sandbox Code Playgroud)
数据框最初按列排序,bar并且foo可以从中获得
df.sort_values(['bar', 'foo'])
Run Code Online (Sandbox Code Playgroud)
我需要df按foo一个bar来排序。显而易见的解决方案是
df.sort_values(['foo', 'bar'])
Run Code Online (Sandbox Code Playgroud)
这给了我
foo bar buzz
0 1 A 10
3 1 B 20
6 1 M 20
1 2 A 20
4 2 B 20
7 2 M 30
2 3 A 30
5 3 B 10
8 3 M 30
Run Code Online (Sandbox Code Playgroud)
但现实世界的数据帧包含大约 500,000 行,我有大约 3,000 个单独的数据帧要处理。
我想知道是否有更好、更有效的解决方案来考虑数据框已经预先排序的事实?
您可以在这里利用稳定排序,因为bar已经排序,这意味着您只需要重新排序foo。
这应该对所有大小的 DataFrame 的运行时产生一致的影响(我看到全面加速大约 2 倍)。
这是一个使用numpy's的示例解决方案argsort,指定一个稳定的排序。
df.iloc[np.argsort(df['foo'], kind="stable")]
Run Code Online (Sandbox Code Playgroud)
foo bar buzz
0 1 A 10
3 1 B 20
6 1 M 20
1 2 A 20
4 2 B 20
7 2 M 30
2 3 A 30
5 3 B 10
8 3 M 30
Run Code Online (Sandbox Code Playgroud)
性能和验证
df = pd.DataFrame(
{
"foo": np.random.randint(0, 100, 100_000),
"bar": np.random.choice(list("ABCDEFGHIJKLMNOP"), 100_000),
"buzz": np.random.randint(0, 100, 100_000),
}
).sort_values(["bar", "foo"])
In [42]: %timeit df.iloc[np.argsort(df['foo'], kind="stable")]
3.41 ms ± 22.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [43]: %timeit df.sort_values(["foo", "bar"])
6.95 ms ± 136 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [48]: a = df.iloc[np.argsort(df['foo'], kind="stable")]
In [49]: b = df.sort_values(["foo", "bar"])
In [50]: np.all(a == b)
Out[50]: True
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
84 次 |
| 最近记录: |