Zscore使用groupby

时间:2017-07-03 15:49:01

标签: python pandas numpy scipy

我有一个代表客户订单的数据框,其中有许多列,其中两个是' user_id'和'美元'。

例如:

    user_id   dollar 
0  1  0.34592  5
1  1  0.02857  7
2  1  0.26672  6
3  1  0.34592  5
4  1  0.02857  9
5  1  0.26672  10
6  1  0.34592  6
      [...]
7  40  0.02857  20
8  40  0.26672  19
9  40  0.34592  8
10 40  0.02857  18
11 40  0.26672  26

我希望将美元价值相对于每个用户行中的其他值进行标准化。我想要上一个例子的以下结果:

 user_id   dollar norm_dollar
0  1  0.34592  5  -1.02774024
1  1  0.02857  7  0.07905694
2  1  0.26672  6  -0.47434165
3  1  0.34592  5  -1.02774024
4  1  0.02857  9  1.18585412
5  1  0.26672  10  1.73925271
6  1  0.34592  6  -0.47434165
      [...]
7  40  0.02857  20  0.7787612
8  40  0.26672  19  0.57109154
9  40  0.34592  8   -1.71327463
10 40  0.02857  18  0.36342189

编辑:

我希望每个用户单独归一化每个结果,而不是整列的值,因此例如对于user2,[20,19,8,18]应该归一化,好像均值是平均值user2 order,这里的平均值是16,25,而不是整个dataframe列的平均值。

我知道如何与一位用户合作:

user1 = data.loc[data['user_id']==1]
data.loc[data['user_id']==1]['norm_dollar'] = sp.stats.mstats.zscore(user1['dollar'])

我试图以这种方式为所有用户这样做:

data.dollar.div(sp.stats.mstats.zscore(data.groupby('user_id').dollar))

但是我收到了错误,你对如何继续有任何想法吗?

谢谢

2 个答案:

答案 0 :(得分:1)

执行此操作的不同方法 - 例如将groupby数据框加入原始数据框 - 但我开始喜欢使用transform这样的内容。

语法仍然很冗长,但我认为它比join方法更具可读性。

df['norm_dollar'] = (df['dollar']
                        - df.groupby('user_id')['dollar'].transform(np.mean)) \
                        / df.groupby('user_id')['dollar'].transform(np.std)

如果您需要在np.std上指定自由度,可以将其转换为

lambda x: np.std(x, ddof=n)

答案 1 :(得分:1)

那应该适合你:

def apply_zscores(x):
    x['norm_dollar'] = zscore(x['dollar'])
    return x

df = df.groupby('id').apply(lambda x: apply_zscores(x))