2016-02-04 125 views
1

我有兩個dataframes,功能花費很長的時間在Python運行 - 效率

df1 = pd.DataFrame({'a': [1.5, 2.5], 'b': [0.25, 2.75], 'c': [1.25, 0.75], 'd': [1.5, 2.5],'e': [0.25, 2.75], 'f': [1.25, 0.75]}) 

df2 = pd.DataFrame({'a': [1.5, 2.5,3.5,4.5], 'b': [0.25, 1.5, 2.5, 2.75], 'c': [1.25, 0.75, 3.5, 4.5], 'd': [1.5, 2.5, 3.5, 4.5],'e': [0.25, 2.75, 1.5, 3.5], 'f': [1.25, 0.75, 2.5, 4.5]}) 

對於DF1每一行,我要找到該行的距離,DF2的所有行的具體列。找到距離後,我想找到所有單行中的最小距離,並返回df2對應的'e'值。

例如,如果我傳遞a和b列,對於df1的每一行,我想要找到a和b之間的所有df2行的距離,並找到所有行的最小距離並獲得相應的'e' df2的值。

我使用以下兩種功能,

def distance(x1, x2, L): 
    start_time = time.time() 
    dist = (np.sum((np.array(x1)-np.array(x2))**L))**(1/(float(L))) 
    print("Time taken: " + str(round(time.time() - start_time,2)) + " seconds") 
    return dist 

def mindistance(data1,data2,variables,L): 
    start_time = time.time() 
    pred_values=[] 
    test1=[] 
    for index2, row2 in data2.iterrows(): 
     test=[] 
     for index1, row1 in data1.iterrows(): 
      a=distance(row2[variables],row1[variables],L) 
      test.append(a) 
     #print(test) 
     index=test.index(min(test)) 
     #print(index) 
     b=round(data1['e'].iloc[index],2) 
     pred_values.append(b) 

    print(pred_values) 
    print(len(pred_values)) 
    return "Time taken: " + str(round(time.time() - start_time,2)) + " seconds" 

print mindistance(df2, df1,['a','b'],2) 

此功能工作正常。但是這個代碼存在一個巨大的效率問題。距離部分需要很長時間。假設如果基於我的原始數據框大約有60000次迭代需要完成,則計算它需要一分多鐘。我已經嘗試了逐行調試,大部分時間都在a=distance(row2[variables],row1[variables],L)行中。任何人都可以幫助我提高代碼的效率嗎?

+0

你分析了你的代碼嗎?如果使用'apply'而不是顯式迭代數據框會發生什麼? –

+0

@PaulH我很抱歉,我是python的新手。不知道什麼是分析,不知道如何使用應用函數?你能幫我做這件事嗎? – haimen

+0

分析python代碼:http://stackoverflow.com/questions/3927628/how-can-i-profile-python-code-line-by-line –

回答

3

以下是如何使用apply重寫mindistance function

def mindistance(data1,data2,variables,L): 
    start_time = time.time() 
    pred_values=[] 
    test1=[] 
    for index2, row2 in data2[variables].iterrows(): 
     test=list(data1[variables].apply(distance, args=(row2,L,), axis=1)) 
     index=test.index(min(test)) 
     #print index 
     b=round(data1['e'].iloc[index],2) 
     pred_values.append(b) 

    #print pred_values 
    #print len(pred_values) 
    return "Time taken: " + str(round(time.time() - start_time,2)) + " seconds" 

這將帶來顯着改善。你可以進一步將另一個循環轉換爲apply

+0

非常感謝! – haimen

+0

不客氣 – innoSPG