Pandas按组聚合agg标准差NaN

11

输入:

df['PopEst']
    .astype('float')
    .groupby(ContinentDict)
    .agg(['size','sum','mean','std']))

输出:

            size            sum                mean              std
Asia          5     2.898666e+09       5.797333e+08     6.790979e+08
Australia     1     2.331602e+07       2.331602e+07              NaN
Europe        6     4.579297e+08       7.632161e+07     3.464767e+07
North America 2     3.528552e+08       1.764276e+08     1.996696e+08
South America 1     2.059153e+08       2.059153e+08              NaN

如果一个分组只有一行数据,那么std列中的某些值会变成NaN,但我认为这些值应该是0,为什么会这样?

2个回答

13

pd.DataFrame.std 默认情况下假设1个自由度,也称为样本标准差。这会导致对于只有一个数字的组产生NaN结果。

相比之下,numpy.std 默认情况下假设0个自由度,也称为总体标准差。这会使得只有一个数字的组得到0

要了解样本和总体之间的区别,请参见Bessel's correction

因此,您可以指定使用numpy.std进行计算。然而请注意,由于计算方式不同,输出结果将不同。以下是一个最简示例。

import pandas as pd, numpy as np

df = pd.DataFrame(np.random.randint(0, 9, (5, 2)))

def std(x): return np.std(x)

res = df.groupby(0)[1].agg(['size', 'sum', 'mean', std])

print(res)

   size  sum  mean       std
0                           
0     2   13   6.5       0.5
4     1    3   3.0       0.0
5     1    3   3.0       0.0
6     1    3   3.0       0.0

或者,如果您需要一个自由度,可以使用fillnaNaN值替换为0

res = df.groupby(0)[1].agg(['size', 'sum', 'mean', 'std']).fillna(0)

3
谢谢您的回答!当我将代码更改为.agg('size','sum','mean',np.std)时,_输出_仍然保持NaN。但是当我使用lambda x:np.std(x)代替时,NaN变成了0,这正是我想要的。我想知道为什么会发生这种情况。 - Alex J
如果我想在调用.agg([np.mean, np.std])时更改ddof怎么办?我尝试使用.agg([np.mean, np.std], ddof=0)将其作为外部参数传递,但它不起作用。 - FrancescoLS
1
@FrancescoLS,我能想到的最好方法是使用高阶函数functools.partial,然后使用partial(np.std, ddof=1)partial(np.std, ddof=2)等。 - jpp
@FrancescoLS 为什么使用 return np.std(x, ddof=0) 可以解决问题?在文档 https://numpy.org/doc/stable/reference/generated/numpy.std.html 中,ddof 的默认值为 0。 - torayeff
@torayeff 我最初的问题是由于pandas和numpy中ddof的不同默认值而导致结果不同:在pandas中ddof = 1,在numpy中ddof = 0。因此,当使用groupby.agg(std)和在每个组中执行np.std(x)时,我得到了不同的结果。 - FrancescoLS
显示剩余2条评论

0
根据文档np.std(..., ddof=1)默认将 "自由度" 设置为1。要解决您的问题,只需用lambda x: np.std(x, ddof=0)替换np.std即可,然后您的NaN将被更改为0

这个答案似乎不正确。链接的文档是关于 pd.DataFrame.std 的,而答案指定它与 np.std 有关。 - jpp

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