已排序的数据框的排序顺序翻转

3

我有一堆数据帧,其结构如下:

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']
)

数据框最初通过列barfoo进行排序,如下所示:

df.sort_values(['bar', 'foo'])

我需要按照 foobar 排序 df。显而易见的解决方案是:
df.sort_values(['foo', 'bar'])

这让我

   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

但是实际数据框包含大约 500,000 行,我有大约 3,000 个单独的数据框需要处理。

我想知道是否有更好、更高效的解决方案,可以考虑到数据框已经预先排序的事实?


数据框必须按相反的顺序排序有特定的原因吗?在继续之前,我想确保这不是一个 XY 问题 :) - MattR
是的,foo列对应于时间,而bar是一个股票符号。我需要它来优化基于时间的查询的Parquet文件。 - taras
1个回答

5

在这里,您可以利用稳定排序,因为bar已经排序,这意味着您只需要重新排序foo

这应该在所有大小的DataFrame上具有一致的运行时影响(我在整个过程中看到了大约2倍的加速)。

以下是一个解决方案示例,使用numpyargsort,指定了一个稳定的排序。

df.iloc[np.argsort(df['foo'], kind="stable")]

   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

性能和验证

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

1
谢谢!我相信这正是我在寻找的东西。它可能不会给我带来我期望的那么大的改进,但方法本身很棒。 - taras
1
你也可以使用“df.iloc[df.foo.argsort().array]”。我相信它是“np.argsort”的一个包装器。 - sammywemmy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接