首页 > 解决方案 > 如何优化这个 python 脚本 Pandas 的时间?

问题描述

我有需要优化的脚本。示例数据在此处添加data

我尝试了几件事,将 groupby 更改为使用排序值。我已经尝试过更快速地快速申请,但它需要更多时间。

df_loop = pd.read_excel("data.xlsx")

df_loop.index = df_loop["Destination"]

uni_list = df_loop["Destination"].unique()

def get_custcon(x):
    dfa = df_loop[(df_loop.index.isin(x))]
    dfa.sort_values\
    (by = ["Source","Time"],ascending=True).drop_duplicates('Source'\
                                            ,keep='first',inplace = True)
    return  [x,dfa["con"].sum()/dfa["Options"].sum()]



def get_optimisation(site):
    list_site = []
    for si in range(site):
        s = "step_" + str(si) 
        list_site.append(s)
    list_site = ["random_combination"] + list_site + ["Cust"] 
    test_data = pd.DataFrame(columns = list_site)
    Iteration = 1 #how many iteration do you want to run 
    for it in range(Iteration):
        test_list = []
        random_com = tuple(random.sample(set(df_loop["Source"]\
                                              .unique()),site)) ### random combination
        test_list.append(random_com)

        for i in range(site):
            li = list(range(site))
            li.remove(i)
            col_dict = {}
            for k in li:
                j = "site_" + str(k)
                if j not in col_dict:
                    col_dict[j] = [random_com[k]]* 5
            df_com = pd.DataFrame(col_dict)
                
            df_com["site_"+str(i)] = uni_list
            df_com["res"] = df_com.apply(lambda x : get_custcon(list(x)),axis = 1)
            df_com[['combination', 'cust_C']] = df_com['res'].apply(pd.Series)
            
            solution = df_com.loc[df_com["cust_C"].idxmin()][["res"]][0]
            random_com  = tuple(solution[0])
            test_list.append(tuple(solution[0]))
        test_list.append(solution[1])
        test_data.loc[it] = test_list
    return(test_data.loc[test_data["Cust"].idxmin()][test_data.columns[-2]])

start = time.time()
print(list(get_optimisation(2))) # write site number here 
end = time.time()
print("time",end - start)

此代码通常需要 0.038 秒。现在我分享的数据只是样本。我有 250 万行的数据,它需要 75 秒,但我不能为这个过程腾出这么多时间。

我尝试过的代码但没有运气:

def get_custcon(x):
    dfa = df_loop[(df_loop.index.isin(x))]
    dfa.sort_values('Time').groupby('Source').first()
    return  [x,dfa["con"].sum()/dfa["Options"].sum()]


df_com["res"] = df_com.swifter.apply(lambda x : get_custcon(list(x)),axis = 1)

提前致谢。

标签: python-3.xpandasdataframeoptimizationpandas-groupby

解决方案


没有回顾为什么要嵌套 3 个 for 循环,因为您已经说过“慢”部分是get_custcon(x).

旁白:您可能会考虑是否需要嵌套,或者是否有办法在没有 3 个嵌套循环的情况下获得结果

看着get_custcon(x)我看到您正在重复对过滤结果进行排序。我认为您可以排序一次,然后过滤:

df_loop_sorted = df_loop.copy()
df_loop_sorted.sort_values(by = ["Source","Time"], ascending=True).drop_duplicates('Source', keep='first', inplace = True)

def get_custcon(x):
    dfa = df_loop_sorted[(df_loop_sorted["Destination"].isin(x))]
    return  [x,dfa["con"].sum()/dfa["Options"].sum()]

此更改将小数据的执行时间减少了一半。对于更大的数据,它可能更重要。

请注意,根据您可能需要的数据:

drop_duplicates(['Destination', 'Source'], keep='first', inplace=True)

推荐阅读