首页 > 解决方案 > 使用前一行值计算 z 分数

问题描述

我有一个数据框,如下所示:

 ids    value   
  1      0.1
  1      0.2
  1      0.14   
  2      0.22
    ....

我正在尝试遍历每个 id 并为每个 id 计算一个新列“z-score”。

for id, row in df.groupby('ids'):
    row.reset_index(inplace=True)
    row.loc[0, 'z_score'] = 0
    row.loc[1, 'z_score'] = 0

    for i in range (2, len(row)):
        row.loc[i, 'z_score'] = (row.loc[i, value] - row.loc[0:i-1][value].mean()) / row.loc[0:i-1][value].std()
    print(row)
    # How to add each "row" back to the original dataframe? 

前两个的 z 分数应该为 0。然后使用之前的值(最多 i-1)来计算 z 分数的每次迭代的平均值和标准差。我的 df 看起来像这样:

 ids    value    z_score    
  1      0.1       ..              
  1      0.2       ..            
  1      0.14      ..          
  2      0.22      ..            
     ....

标签: pythonpandas

解决方案


使用scipy.stats.zscore

from scipy.stats import zscore

df['zscore'] =  df.groupby('ids')['value'].transform(zscore)
print(df)
   ids  value    zscore
0    1   0.10 -1.135550
1    1   0.20  1.297771
2    1   0.14 -0.162221
3    2   0.22       NaN

或者,坚持熊猫,

df['zscore'] = df.groupby('ids').value.apply(
                    lambda x: (x - x.mean()) / x.std(ddof=0))
print(df)
       ids  value    zscore
    0    1   0.10 -1.135550
    1    1   0.20  1.297771
    2    1   0.14 -0.162221
    3    2   0.22       NaN

如果您想要扩展 zscore,请尝试groupby+ expanding

g = df.groupby('ids').value.expanding(min_periods=1)
df['zscore'] = (df['value'] - g.mean().values) / g.std(ddof=0).values

print(df)
   ids  value    zscore
0    1   0.10       NaN
1    1   0.20  1.000000
2    1   0.14 -0.162221
3    2   0.22       NaN

推荐阅读