在DataFrameGroupBy.agg中,sum(min_count=1)是否与sum一样快速?

0 投票
3 回答
95 浏览
提问于 2025-04-12 23:00

我有一个包含几百万行的数据表,我通过某种方式对它进行分组,然后对几个列进行求和,代码如下:

df.groupby(…).agg({
  "foo": "sum",
  "bar": "sum",
  …})

这个过程相当快,我的电脑上大约需要10秒钟。

现在我需要一种求和的变体,它可以保留NaN值,比如说:

sum(min_count=1)

看起来要想用上面提到的分组和聚合方法实现这个功能,只能通过以下方式:

... agg({
  "foo": (lambda s: s.sum(min_count=1))
})

但是这样做的速度慢了10倍。

我尝试传递一些参数,但当我把一个字典传给聚合方法时,这些参数似乎没有被使用:

... agg({
  "foo": "sum",
  "bar": "sum",
}, min_count=1)

有没有办法在保持min_count=1的语义的同时,达到和简单求和一样的速度呢?

3 个回答

0

你可以尝试的一种方法是直接在自定义的聚合函数中使用numpy。

import numpy as np

def sum_with_min_count(s):
    return np.nansum(s.to_numpy())

result = df.groupby(...).agg({
    "foo": sum_with_min_count,
    "bar": sum_with_min_count,
    # Add other columns as needed
})
1

如果你在所有列上使用 sum 作为聚合函数,你可以这样做:

df.groupby(...).sum(min_count=1)

以这个数据框为例:

   a    b    c
0  1  NaN  NaN
1  1  NaN  NaN
2  2  1.0  3.0
3  2  2.0  4.0

这样做:

df.groupby("a").sum(min_count=1)

会返回:

     b    c
a          
1  NaN  NaN
2  3.0  7.0

如果你想对特定的列进行聚合,可以在分组后选择它们:

   a    b    c    d
0  1  NaN  NaN  NaN
1  1  NaN  NaN  NaN
2  2  1.0  3.0  0.0
3  2  2.0  4.0  0.0

比如选择 'b''c'

df = df.groupby("a")[["b", "c"]].sum(min_count=1)

会返回:

     b    c
a          
1  NaN  NaN
2  3.0  7.0
2

我觉得问题的关键在于,你可以把:

df.groupby(...).agg({"col1": func0, "col2": func0})

替换成:

df.groupby(...)[["col1", "col2"]].func0()

在你的例子中:

>>> df = pd.DataFrame({"x": list("aabbbaa"), "y": [1,1,None,None,None,None,None], "z": [None,None,3,None,None,None,None]})
>>> df.groupby("x")[["y", "z"]].sum(min_count=1)
     y    z
x
a  2.0  NaN
b  NaN  3.0

这让你可以充分利用 pd.DataFrame.sum() 的所有功能,具体可以参考 文档

撰写回答