熊猫将自定义功能应用于由另一列分组的一列的每一行

时间:2018-11-28 17:26:46

标签: python-3.x pandas

我有一个包含两列的数据框:idval

df = pd.DataFrame ({'id': [1,1,1,2,2,2,3,3,3,3], 'val' : np.random.randn(10)})

   id       val
0   1  2.644347
1   1  0.378770
2   1 -2.107230
3   2 -0.043051
4   2  0.115948
5   2  0.054485
6   3  0.574845
7   3 -0.228612
8   3 -2.648036
9   3  0.569929

我想根据val将自定义函数应用于每个id。假设我要应用最小-最大缩放。这就是我使用for循环的方式:

df['scaled']=0
ids = df.id.drop_duplicates()
for i in range(len(ids)):
    df1 = df[df.id==ids.iloc[i]]
    df1['scaled'] = (df1.val-df1.val.min())/(df1.val.max()-df1.val.min())
    df.loc[df.id==ids.iloc[i],'scaled'] = df1['scaled']

结果是:

   id       val    scaled
0   1  0.457713  1.000000
1   1 -0.464513  0.000000
2   1  0.216352  0.738285
3   2  0.633652  0.990656
4   2 -1.099065  0.000000
5   2  0.649995  1.000000
6   3 -0.251099  0.306631
7   3 -1.003295  0.081387
8   3  2.064389  1.000000
9   3 -1.275086  0.000000

我该如何快速无循环执行此操作?

2 个答案:

答案 0 :(得分:3)

您可以使用groupby进行此操作:

In [6]: def minmaxscale(s): return (s - s.min()) / (s.max() - s.min())                                                                                           

In [7]: df.groupby('id')['val'].apply(minmaxscale)                                                                                                            
Out[7]: 
0    0.000000
1    1.000000
2    0.654490
3    1.000000
4    0.524256
5    0.000000
6    0.000000
7    0.100238
8    0.014697
9    1.000000
Name: val, dtype: float64

(请注意,np.ptp() /峰峰值可用于放置s.max() - s.min()。)

这会将功能minmaxscale()应用于val分组的每个较小的id系列。

以第一组为例,

In [11]: s = df[df.id == 1]['val']                                                                                                                            

In [12]: s                                                                                                                                                    
Out[12]: 
0    0.002722
1    0.656233
2    0.430438
Name: val, dtype: float64

In [13]: s.max() - s.min()                                                                                                                                    
Out[13]: 0.6535106879021447

In [14]: (s - s.min()) / (s.max() - s.min())                                                                                                                  
Out[14]: 
0    0.00000
1    1.00000
2    0.65449
Name: val, dtype: float64

答案 1 :(得分:2)

来自sklearn MinMaxScaler

的解决方案
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
df['new']=np.concatenate([scaler.fit_transform(x.values.reshape(-1,1)) for y, x in df.groupby('id').val])
df
Out[271]: 
   id       val    scaled       new
0   1  0.457713  1.000000  1.000000
1   1 -0.464513  0.000000  0.000000
2   1  0.216352  0.738285  0.738284
3   2  0.633652  0.990656  0.990656
4   2 -1.099065  0.000000  0.000000
5   2  0.649995  1.000000  1.000000
6   3 -0.251099  0.306631  0.306631
7   3 -1.003295  0.081387  0.081387
8   3  2.064389  1.000000  1.000000
9   3 -1.275086  0.000000  0.000000