分组数据帧Pandas上的高效操作



我有一个非常大的Pandas数据帧,我需要在基于另一列的组内进行排序。我知道如何迭代组,对组执行操作,并将所有这些组联合回一个数据帧,但这很慢,我觉得有更好的方法可以实现这一点。这是输入和我想要的。输入:

ID   price
1    100.00
1    80.00
1    90.00
2    40.00
2    40.00
2    50.00

输出:

ID   price  order
1    100.00 3
1    80.00  1
1    90.00  2
2    40.00  1
2    40.00  2 (could be 1, doesn't matter too much)
2    50.00  3

由于这是超过5千个记录和大约25万个ID,因此效率很重要。

如果速度是你想要的,那么下面的应该很好,尽管它有点复杂,因为它使用了numpy中的复数排序。这类似于在包numpy-groupies中编写聚合排序方法时使用的方法(my me)。

# get global sort order, for sorting by ID then price
full_idx = np.argsort(df['ID'] + 1j*df['price'])
# get min of full_idx for each ID (note that there are multiple ways of doing this)
n_for_id = np.bincount(df['ID'])
first_of_idx = np.cumsum(n_for_id)-n_for_id 
# subtract first_of_idx from full_idx
rank = np.empty(len(df),dtype=int)
rank[full_idx] = arange(len(df)) - first_of_idx[df['ID'][full_idx]]
df['rank'] = rank+1

在我的机器上,5米行需要2秒,这比使用Panda的groupby.rank快了大约100倍(尽管我实际上没有运行5米行的Panda版本,因为这需要太长时间;我不确定@ayhan是如何在30秒内完成的,也许这与Panda版本不同?)。

如果你确实使用了这个,那么我建议彻底测试它,因为我没有。

您可以使用秩:

df["order"] = df.groupby("ID")["price"].rank(method="first")
df
Out[47]: 
   ID  price  order
0   1  100.0    3.0
1   1   80.0    1.0
2   1   90.0    2.0
3   2   40.0    1.0
4   2   40.0    2.0
5   2   50.0    3.0

在一个包含250000个ID(i5-3330)的5m行数据集上,大约需要30秒:

df = pd.DataFrame({"price": np.random.rand(5000000), "ID": np.random.choice(np.arange(250000), size = 5000000)})
%time df["order"] = df.groupby("ID")["price"].rank(method="first")
Wall time: 36.3 s

最新更新