使用Python Pandas计算分组平均值的Z分数

3

I have a dataframe like this:

df = pd.DataFrame({'Year' : ['2010', '2010', '2010', '2010', '2010', '2011', '2011', '2011', '2011', '2011', '2012', '2012', '2012', '2012', '2012'],
                   'Name' : ['Bob', 'Joe', 'Bill', 'Bob', 'Joe', 'Dave', 'Bob', 'Joe', 'Bill', 'Bill', 'Joe', 'Dave', 'Dave', 'Joe', 'Steve'],
                    'Score' : [95, 76, 77, 85, 82, 92, 67, 80, 77, 79, 82, 92, 64, 71, 83]})

我希望能够为每个Name在每个Year中获得Z分数。

如果按以下方式对Year列进行子集处理,我就可以完成它:

(df[df.Year == '2010'].groupby(['Year', 'Name'])['Score'].mean() - df[df.Year == '2010'].groupby(['Year', 'Name'])['Score'].mean().mean()) / ( df[df.Year == '2010'].groupby(['Year', 'Name'])['Score'].mean().std())

有没有更简洁的方法?

1个回答

1

scipy中有一个zscore功能,但要注意在scipy.stats.zscore中默认的自由度为0:

In [171]:
import scipy.stats as ss
S=(df[df.Year == '2010'].groupby(['Year', 'Name'])['Score'].mean())
pd.Series(ss.zscore(s, ddof=1), S.index)
Out[171]:
Year  Name
2010  Bill   -0.714286
      Bob     1.142857
      Joe    -0.428571
dtype: float64

我已经有些生疏了,但是对于z-score来说,ddof不应该是0吗?我认为它是相对于总体统计而言定义的,而不是样本统计(与t-score相比)。 - DSM
@DSM,我认为:不完全是这样。Z分数是差异与平均值之比除以标准偏差。如果我们选择默认值,则stats.zscore使用的标准偏差为ddof==0,这可能不是我们想要的(并且与pandas默认值不同)。为了匹配OP的结果,需要使用ddof=1 - CT Zhu
@DSM,而且,要得到t分数,我们需要进一步除以“sqrt(N)”,其中“N”是样本大小。 - CT Zhu
现在我更加困惑了——我原以为z分数和t分数是等价的,但在z分数中我们使用总体均值和总体标准差,在t分数中我们使用样本均值和样本标准差。(你有解释额外sqrt(N)因子的链接吗?)我可以理解使用ddof = 1,但我认为那不再是Z分数了,对吗? - DSM
@DSM,很抱歉让您更加困惑。为了解释它们之间的区别,基本上正态分布和t分布以及它们的应用之间的差异将涉及一些内容,并需要一些好的例子。我最喜欢的解释在第7.9节,第169-173页:http://books.google.com/books/about/Biometry.html?id=N6KCNw5NHNkC - CT Zhu

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