2017-05-06 37 views
0

我想根据执行时间优化我的代码。代码运行在数据框alldata上,其中包含大约300,000个条目,但计算需要很长时间(大约10个小时左右)。根据执行时间优化嵌套for循环

计算的逻辑如下:

对于每个缺少的(楠)数据帧中的列的列表中的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 

是否可以优化代码?例如,我正在考虑用函数代替函数。可能吗?

+0

如何使您的for-loops'lambda'函数有所帮助?为什么'lambda'函数而不是普通函数? –

+0

@ juanpa.arrivillaga这是我的假设,因为我在读'apply(lambda x:...)'比循环更快。 – Dinosaurius

+0

它*当然不是*。 'pandas.DataFrame.apply'是引擎盖下的一个python for-loop。 –

回答

1

而是与lambdas替换您的for循环中,尝试用ufuncs.

Losing Your Loops: Fast Numerical Computation with Numpy取代他们的是关于这个问题的一个很好的谈话由Jake Vanderplass。 使用通用函数和广播代替for循环可以显着提高代码的速度。

这是一个基本的例子:

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 

输入:

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

OUTPUT:

ran sums in 0.030008554458618164 seconds 
ran sums_broadcasted in 0.0005011558532714844 seconds 

注意消除我们的循环,我们有一个60倍的速度提升!