功能需要很长时间才能在Python中运行 - 效率

时间:2016-02-04 18:53:20

标签: python pandas

我有两个数据帧,

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行的距离。找到距离后,我想找到所有行中的最小距离并返回相应的' e' df2的值。

例如,如果我传递a和b列,对于df1的每一行,我想找到df2中所有行的a和b之间的距离,并找到所有行的最小距离并得到相应的' 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)行。任何人都可以帮助我提高代码效率吗?

1 个答案:

答案 0 :(得分:3)

以下是使用mindistance function重写apply的方法。

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的调用来进一步发展。