【发布时间】:2021-09-11 18:47:45
【问题描述】:
我有一个 pandas 数据框,如下所示(大约 100 万行):
Column_1 Column_2 Column_3 Column_4 Column_5 Column_6 Column_7 Column_8 Column_9 Column_10
… … … … … … … … … …
… … … … … … … … … …
… … … … … … … … … …
… … … … … … … … … …
我想做:
grouping = ["Column_1", "Column_2", "Column_3", "Column_4"]
df.groupby(grouping).apply(lambda x: pd.Series({
'new_column_1':func_1(x),
'new_column_2':func_2(x),
'new_column_3':func_3(x)}
)).reset_index()
这可行,但速度非常慢。函数 [func_1, func_2, func_3] 是我想应用于每个组的自定义函数。
我阅读了其他关于为什么这么慢的堆栈溢出讨论。我发现的原因是 pandas groupby + apply 使用 python 循环而不是矢量化。但是,我怎样才能加快速度呢?
例如,假设:
def func_1(x) {
return sum(x["Column_5"] >= x["Column_6"]) / sum(x["Column_5"] <= x["Column_6"])
}
def func_2(x) {
return max(x["Column_8"]) + min(x["Column_9"])
}
def func_3(x) {
return len(x)
}
如果没有 pandas groupby + numpy,我们怎么能做同样的操作?
【问题讨论】:
-
groupby+apply默认在组上循环。相反,您想根据内置的 groupby 聚合重新编写聚合,这些聚合都在cython中进行了优化。比如func_3就是GroupBy.size(),fun_2可以写成两个独立的GroupBy.min() + GroupBy.max。两个单独的 groupbys 会更快,因为.groupby()并没有真正做任何事情:stackoverflow.com/questions/63306888/… -
“向量化”是指在编译后的代码中执行循环。这需要对
pandas或numpy有足够的了解,才能知道哪些操作(通常是methods)是这些快速(呃)构建块。我对pandas的内部结构了解不多,但对于numpy,更快的东西以“并行”方式与整个数字数组一起工作。它确实在低级别进行迭代,但您作为用户并不关心顺序。 -
@ALollz 我实际上是做了 fun_2 和 fun_3,但在这个例子中我真正需要的是 fun_1。有没有办法用 pandas groupby 聚合来做到这一点?否则,我可以使用 numpy,但是如何复制 groupby 逻辑?
-
numpy没有groupby工具。
标签: python pandas numpy vectorization