python 与itertools组合配对-在大量数据上执行长代码

iyfjxgzm  于 2023-09-29  发布在  Python
关注(0)|答案(2)|浏览(100)

我的工作任务,以获得所有可能的组合(对)的ID的(公司)partipated在一个投标,并创建一个新的 Dataframe 与ID_1,ID_2,匹配参数(投标ID)。
我已经准备了以下两个函数,它们提供了我所需的结果,但是当应用于超过500 k行的df时,执行时间超过了几个小时。

import pandas as pd
from itertools import combinations
def get_pairs(dataframe, items):
   return (
       (c1, c2, item)
       for item in items
       for c1, c2 in combinations(dataframe[dataframe['tender_product'] == item]['ID_name'], 2)
   )
def get_all_pairs(df):
        pairs = get_pairs(df,df['tender_product'])
        df= pd.DataFrame(pairs, columns=['ID_name1', 'ID_name2','tender_product'])
        df=df.query('ID_name1 != ID_name2')
        df=df.drop_duplicates()
        df['pair'] = df['ID_name1'].astype(str)+'_'+df['ID_name2'].astype(str)
        df['reversed_pair'] =df['ID_name1'].astype(str)+'_'+df['ID_name2'].astype(str)
        return df

有哪些选项可以优化代码,使其在相同的结果下工作得更快?
初始数据样本:
| ID|嫩产品|
| --|--|
| 1 |招标_1|
| 2 |招标_1|
| 3 |招标_2|
| 4 |招标_2|
电流输出样本:
| ID1| ID2|嫩产品|对|反向线对|
| --|--|--|--|--|
| 1 | 2 |招标_1| 1_2|第二个_1|
| 3 | 4 |招标_2| 3_4| 4_3|

nqwrtyyt

nqwrtyyt1#

我不确定这会有多高效(我没有500 K行来测试!):))但这应该做你想要的吗?

import pandas as pd
data = {'ID': [1,2,3,4,5,6,7,8],
        'tender_product': ['tender_1', 'tender_1', 'tender_2', 'tender_2', 'tender_3', 'tender_3', 'tender_4', 'tender_4']}
df = pd.DataFrame(data)

new_df = df.groupby('tender_product')['ID'].apply(list).reset_index() #Group by tender product and send matching IDs to a list stored in the result column
new_df.rename(columns={'ID': 'ID1'}, inplace=True) #Rename column to ID1
new_df['ID2'] = new_df['ID1'].apply(lambda x: x[1]) #Extract value from list at position 1 (second value in list)
new_df['ID1'] = new_df['ID1'].apply(lambda x: x[0]) #Extract value fromlist at position 0 (first value in list)

注意:这里的顺序很重要。如果我们先替换ID 1值,则该单元格中保存的列表将不再存在,因为我们已经替换了它

最后,我们在两个新列中创建ID的组合

new_df['pair'] = new_df.apply(lambda row: f"{row['ID1']}_{row['ID2']}", axis=1)
new_df['reversed_pair'] = new_df.apply(lambda row: f"{row['ID2']}_{row['ID1']}", axis=1)

在Jupyter中测试:

wpcxdonn

wpcxdonn2#

谢谢你的回答!首先,我明白所使用的项目不是最佳的,改为.unique()。进一步应用group.by()如下

def get_pairs(dataframe:pd.DataFrame,items:list):
num = len(items)
pairs = []

# grouping
dat_gr = dataframe.groupby(['tender_product'])

# cur - progress tracker
# item - current item
# dat_df - data for the item
for cur,(item,dat_df) in enumerate(dat_gr,1):
    prc = cur / num; print(f"Текущий прогресс: {cur} из {num} ({prc:0.0%})", item)

    # Series with IDs 
    cmp_sr = dat_df['ID']        
    if len(cmp_sr) > 1:
        pairs.extend( (str(c1), str(c2), item) for c1, c2 in combinations(cmp_sr.tolist(), 2) )

return pairs

相关问题