组内加权zscore

时间:2017-04-14 22:56:17

标签: python pandas numpy

考虑以下数据框df

np.random.seed([3,1415])
df = pd.DataFrame(dict(
        S=np.random.rand(20),
        W=np.random.rand(20),
        G=np.random.choice(list('ABCD'), 20)
    ))

print(df)

    G         S         W
0   B  0.444939  0.278735
1   D  0.407554  0.609862
2   C  0.460148  0.085823
3   B  0.465239  0.836997
4   A  0.462691  0.739635
5   A  0.016545  0.866059
6   D  0.850445  0.691271
7   C  0.817744  0.377185
8   B  0.777962  0.225146
9   C  0.757983  0.435280
10  C  0.934829  0.700900
11  A  0.831104  0.700946
12  C  0.879891  0.796487
13  A  0.926879  0.018688
14  D  0.721535  0.700566
15  D  0.117642  0.900749
16  D  0.145906  0.764869
17  C  0.199844  0.253200
18  B  0.437564  0.548054
19  A  0.100702  0.778883

我想在'S'定义的每个组中使用权重'W'执行'G'列的加权zscore

因此我们知道加权zscore的定义是什么,这是你在整个集合中计算它的方式:

(df.S - (df.S * df.W).mean()) / df.S.std()

问题(S)
最优雅的计算方法是什么?
最有效的计算方法是什么?
计算此数据的最省时的方法是什么?

我把答案计算为

0     1.291729
1     0.288806
2     0.394302
3     1.414926
4     0.619677
5    -0.461462
6     1.625974
7     1.645083
8     3.312825
9     1.436054
10    2.054617
11    1.512449
12    1.862456
13    1.744537
14    1.236770
15   -0.586493
16   -0.501159
17   -0.516180
18    1.246969
19   -0.257527
dtype: float64

2 个答案:

答案 0 :(得分:2)

你走了:

>>> df.groupby('G').apply(lambda x: (x.S - (x.S * x.W).mean()) / x.S.std())
G    
A  4     0.619677
   5    -0.461462
   11    1.512449
   13    1.744537
   19   -0.257527
B  0     1.291729
   3     1.414926
   8     3.312825
   18    1.246969
C  2     0.394302
   7     1.645083
   9     1.436054
   10    2.054617
   12    1.862456
   17   -0.516180
D  1     0.288806
   6     1.625974
   14    1.236770
   15   -0.586493
   16   -0.501159
Name: S, dtype: float64

我们首先在G中拆分每个组,然后将加权的z-score函数应用于每个组数据框。

答案 1 :(得分:0)

transform

P = df.S * df.W
m = P.groupby(df.G).transform('mean')
z = df.groupby('G').S.transform('std')
(df.S - m) / z

0     1.291729
1     0.288806
2     0.394302
3     1.414926
4     0.619677
5    -0.461462
6     1.625974
7     1.645083
8     3.312825
9     1.436054
10    2.054617
11    1.512449
12    1.862456
13    1.744537
14    1.236770
15   -0.586493
16   -0.501159
17   -0.516180
18    1.246969
19   -0.257527
dtype: float64

agg + join + eval

f = dict(S=dict(Std='std'), P=dict(Mean='mean'))
stats = df.assign(P=df.S * df.W).groupby('G').agg(f)
stats.columns = stats.columns.droplevel()
df.join(stats, on='G').eval('(S - Mean) / Std')

0     1.291729
1     0.288806
2     0.394302
3     1.414926
4     0.619677
5    -0.461462
6     1.625974
7     1.645083
8     3.312825
9     1.436054
10    2.054617
11    1.512449
12    1.862456
13    1.744537
14    1.236770
15   -0.586493
16   -0.501159
17   -0.516180
18    1.246969
19   -0.257527
dtype: float64

天真的时间

enter image description here