2017-10-13 49 views
1

我是熊貓新手。我寫了一個我想優化的代碼,但我不知道如何。我意識到'apply'和'pandas'矢量化比'iterrows'更快的事實,但不知道如何使用它們來實現相同的目標。因爲它與'for'循環類似,所以我很容易使用它,所以我習慣了它。 這裏是我的代碼:優化熊貓代碼:取代'iterrows'和其他想法

import numpy as np 
import pandas as pd 
import matplotlib.pyplot as plt 
from sklearn.metrics import mean_squared_error 
from scipy.spatial.distance import euclidean 
data = pd.read_csv(r'C:\temp\train.txt') 

def group_df(df,num): 
    ln = len(df) 
    rang = np.arange(ln) 
    splt = np.array_split(rang,num) 
    lst = [] 
    finel_lst = [] 
    for i,x in enumerate(splt): 
     lst.append([i for x in range(len(x))]) 
    for k in lst: 
     for j in k: 
      finel_lst.append(j) 
    df['group'] = finel_lst 
    return df 
def KNN(dafra,folds,K,fi,target):   
    df = group_df(dafra,folds) 
    avarge_e = [] 
    for i in range(folds): 
     train = pd.DataFrame(df.loc[df['group'] != i]) 
     test = pd.DataFrame(df.loc[df['group'] == i]) 
     test.loc[:,'pred_price'] = np.nan 
     test.loc[:,'rmse'] = np.nan 
     train.loc[:,'dis'] = np.nan 
     train = train.reset_index() 
     test = test.reset_index() 
     for index,row in test.iterrows(): 
      for index2,row2 in train.iterrows(): 
       train.loc[index2]['dis'] = euclidean(row2[fi],row[fi]) 

正如你所看到的,有2嵌套 'iterrows' 循環。頂部還有1個小'for'循環。 這個代碼的想法是分配測試的每一行之間的歐幾里得距離列車的每一行。但是,由於測試通過'for'循環進行了更改,它最終將添加到所有原始DataFrame。

這裏是數據的beggining:

Id MSSubClass MSZoning LotFrontage LotArea Street Alley LotShape \ 
0 1   60  RL   65.0  8450 Pave NaN  Reg 
1 2   20  RL   80.0  9600 Pave NaN  Reg 
2 3   60  RL   68.0 11250 Pave NaN  IR1 

    LandContour Utilities ...  PoolArea PoolQC Fence MiscFeature MiscVal 
\ 
0   Lvl AllPub ...   0 NaN NaN   NaN  0 

1   Lvl AllPub ...   0 NaN NaN   NaN  0 

2   Lvl AllPub ...   0 NaN NaN   NaN  0 

    MoSold YrSold SaleType SaleCondition SalePrice 
0  2 2008  WD   Normal  208500 
1  5 2007  WD   Normal  181500 
2  9 2008  WD   Normal  223500 

[3行×81列]

爲optimaing此代碼任何想法將受到歡迎。謝謝。

+0

你能提供的測試數據? –

+0

你的意思是:我的DataFrame的第一個排隊? –

+0

是的,你想存檔 –

回答

0

我會建議你問題的兩個可能的解決方案:

- 使用scipys distance_matrix

- 寫入自己numpy的功能

的SciPy的解決方案是直接轉發:

import scipy 
import numpy as np 

point_vector_1 = np.random.random((10000,2)) 
point_vector_2 = np.random.random((1000,2)) 
distance_matrix = scipy.spatial.distance_matrix(point_vector_1, point_vector_2) 

在numpy中,我們可以使用外部的ufunc來編寫我們自己的函數。 np.subtract.outer將從兩個向量中給出一個矩陣,類似於外點產品將給出乘法。

def euclidean_distance_matrix(vector_1, vector_2): 
    dis_dim_1 = np.subtract.outer(vector_1.T[0], vector_2.T[0])**2 
    dis_dim_2 = np.subtract.outer(vector_1.T[1], vector_2.T[1])**2 
    euclidean = np.sqrt(dis_dim_1+dis_dim_2) 
    return euclidean 

distance_matrix_2 = euclidean_distance_matrix(point_vector_1, point_vector_2) 

時序:

%timeit scipy.spatial.distance_matrix(point_vector_1, point_vector_2) 
382 ms ± 8.56 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) 
%timeit euclidean_distance_matrix(point_vector_1, point_vector_2) 
150 ms ± 1.33 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) 

編輯: 爲了讓您可以在源的索引通路DF到新的數據幀的原始指數:

dist_array = euclidean_distance_matrix([df1['lat'], df1['long']], [df2['lat'], df2['long']]) 
df_dist = pd.DataFrame(dist_array, index=df1.index, columns=df2.index) 
+0

謝謝您的建議。這是一個很好的解決方案。假設寫我自己的func會丟失DataFrame的索引和標籤,所以我不能確定新矩陣中的矢量是原始矢量中的哪一列或哪一行。有什麼辦法可以預防它嗎? –