2016-08-24 42 views
1

我最近观看欧文张kaggle 1级竞争对手的视频: https://youtu.be/LgLcfZjNF44 他解释编码类别特征,以数值的一种技术,它被称为留一编码。他对分类特征所做的事情是将一个值与每个观测值相关联,这是所有其他具有相同类别的观测值的平均值。熊猫实现了分类功能

我一直试图在使用熊猫的python中实现这个策略。尽管我已经设法建立了一个成功的代码,但事实是,我的数据集大小为数千万,其性能非常缓慢。 如果有人能提出更快的解决方案,我会非常感激。

这是我到目前为止的代码:

def categ2numeric(data, train=True): 
    def f(series): 
     indexes = series.index.values 
     pomseries = pd.Series() 
     for i, index in enumerate(indexes): 
      pom = np.delete(indexes, i) 
      pomseries.loc[index] = series[pom].mean() 
     series = pomseries 
     return series 

    if train: 
     categ = data.groupby(by=['Cliente_ID'])['Demanda_uni_equil'].apply(f) 

,我需要把这个系列:

  159812  28.0 
      464556  83.0 
      717223  45.0 
      1043801 21.0 
      1152917  7.0 
      Name: 26, dtype: float32 

这样:

  159812  39.00 
      464556  25.25 
      717223  34.75 
      1043801 40.75 
      1152917 44.25 
      dtype: float64 

或者数学与索引元素159812是等于所有其他元素的平均值或:

39 =(83 + 45 + 21 + 7)/ 4

回答

3

用系列和元素之和的差值替换系列中的每个元素,然后除以系列的长度减1.假设s是你的系列:

s = (s.sum() - s)/(len(s) - 1) 

输出结果:

159812  39.00 
464556  25.25 
717223  34.75 
1043801 40.75 
1152917 44.25 
+0

这是有帮助谢谢...对于未来的读者,后来我意识到我在我的代码有个错误所以用你的线路是这样的: S =(s.sum() - S)/(LEN(S) - 1)如果len(s)> 1 else s –

1

与@root的帮助,我已经发现,最快的解决这个问题是这样的方法:

cs = train.groupby(by=['Cliente_ID'])['Demanda_uni_equil'].sum() 
cc = train['Cliente_ID'].value_counts() 
boolean = (cc == 1) 
index = boolean[boolean == True].index.values 
cc.loc[boolean] += 1 
cs.loc[index] *= 2 
train = train.join(cs.rename('sum'), on=['Cliente_ID']) 
train = train.join(cc.rename('count'), on=['Cliente_ID']) 
train['Cliente_IDloo'] = (train['sum'] - train['Demanda_uni_equil'])/(train['count'] - 1) 
del train['sum'], train['count'] 

我发现如果使用可调用函数的apply方法作为输入,它需要2分钟,而这种方法只需要1秒,但这有点麻烦。