2017-05-06 17 views
0

実行時間に関してコードを最適化したい。コードは約300,000のエントリを含むデータフレームalldataで実行されますが、計算には非常に長い時間がかかります(約10時間程度)。実行時間に関してネストされたfor-loopsを最適化する

計算ロジックは以下の通りである:

リストlist_of_NA_featuresで指定されたデータフレームの列の各欠落(ナン)値について、最も類似する行を検索fill_missing_values機能(コサイン類似度は、列に基づいて計算されリスト内ではlist_of_non_nan_featuresは空ではありません)、現在の列と行の値をalldataに返します。

from scipy import spatial 

def fill_missing_values(param_nan,current_row,df): 
    df_non_nan = df.dropna(subset=[param_nan]) 
    list_of_non_nan_features = ["f1","f2","f3","f4","f5"] 
    max_val = 0 
    searched_val = 0 
    vector1 = current_row[list_of_non_nan_features].values 
    for index, row in df_non_nan.iterrows(): 
     vector2 = row[list_of_non_nan_features].values 
     sim = 1 - spatial.distance.cosine(vector1, vector2) 
     if (sim>max_val): 
      max_val = sim 
      searched_val = row[param_nan] 
    return searched_val 


list_of_NA_features = df_train.columns[df_train.isnull().any()] 


for feature in list_of_NA_features: 
    for index,row in alldata.iterrows(): 
     if (pd.isnull(row[feature]) == True): 
      missing_value = fill_missing_values(feature,row,alldata) 
      alldata.ix[index,feature] = missing_value 

コードを最適化することは可能ですか?例えば、私はlambda関数でforループの置換について考えています。出来ますか?代わりにlambdasであなたのforループを置換する

+0

for-loopsの 'lambda'関数はどのように役立ちますか?そしてなぜ 'lambda'が通常の関数の代わりに機能するのですか? –

+0

@ juanpa.arrivillaga私が読んでいたのは、 'apply(lambda x:...)'がforループより速いことを読んでいたからです。 – Dinosaurius

+0

※もちろんありません。 'pandas.DataFrame.apply'は、フードの下のPython for-loopです。 –

答えて

1

ufuncs.

Losing Your Loops: Fast Numerical Computation with Numpyでそれらを代入しようとすると、対象のジェイクVanderplassことにより、優れた話です。 for-loopsの代わりにユニバーサル関数とブロードキャストを使用すると、コードのスピードが飛躍的に向上します。

は、ここで基本的な例である:

import numpy as np 
from time import time 

def timed(func): 
    def inner(*args, **kwargs): 
     t0 = time() 
     result = func(*args, **kwargs) 
     elapsed = time()-t0 
     print(f'ran {func.__name__} in {elapsed} seconds)') 
     return result 
    return inner 
# without broadcasting: 

@timed 
def sums(): 
    sums = np.zeros([500, 500]) 
    for a in range(500): 
     for b in range(500): 
      sums[a, b] = a+b 
    return sums 

@timed 
def sums_broadcasted(): 
    a = np.arange(500) 
    b = np.reshape(np.arange(500), [500, 1]) 
    return a+b 

INPUT:

sums() 
sums_broadcasted() 
assert (a==b).all() 

OUTPUT:私たちは60倍のスピードアップを持っている私たちのループを排除することによって

ran sums in 0.030008554458618164 seconds 
ran sums_broadcasted in 0.0005011558532714844 seconds 

注意!

関連する問題