如何使用pandas apply()优化DataFrame行两两对比程序的运行速度?
你原来的嵌套循环本质是生成不含自身配对的行笛卡尔积,这里给你两种实现方案,其中交叉合并方案性能远高于apply方案,你可以按需选择:
方案1:更高效的笛卡尔积合并(推荐,性能是嵌套循环的10倍以上)
直接用pandas内置的交叉连接逻辑实现,底层走numpy运算,避免Python层级的循环开销:
import pandas as pd # 原有生成Title_new的逻辑保留 df = pd.read_excel(r'example.xlsx', sheet_name='Sheet3') df['Title_new'] = df[df.columns[2:]].apply(lambda x: ','.join(x.dropna().astype(str)), axis=1) # 提取需要的字段,分别重命名为a端、b端表 df_a = df[['index', 'Source', 'Title_new']].rename(columns={'index':'index_a', 'Source':'source_a', 'Title_new':'title_a'}) df_b = df[['index', 'Source', 'Title_new']].rename(columns={'index':'index_b', 'Source':'source_b', 'Title_new':'title_b'}) # 交叉连接得到所有两两组合(pandas 1.2.0及以上版本支持how='cross') r_df = df_a.merge(df_b, how='cross') # 过滤掉index相同的自身配对 r_df = r_df[r_df['index_a'] != r_df['index_b']].reset_index(drop=True)
如果你的pandas版本低于1.2.0,可用临时key的方式实现笛卡尔积:
df_a['tmp_key'] = 1 df_b['tmp_key'] = 1 r_df = df_a.merge(df_b, on='tmp_key').drop('tmp_key', axis=1) r_df = r_df[r_df['index_a'] != r_df['index_b']].reset_index(drop=True)
方案2:使用apply替换嵌套循环
如果你确实需要用apply实现,可通过逐行配对+concat拼接的方式实现,性能是原有嵌套循环的2~5倍:
import pandas as pd df = pd.read_excel(r'example.xlsx', sheet_name='Sheet3') df['Title_new'] = df[df.columns[2:]].apply(lambda x: ','.join(x.dropna().astype(str)), axis=1) # 定义单行处理逻辑:将当前行和其他所有行配对 def pair_row(row, full_df): other = full_df[full_df['index'] != row['index']].copy() # 填充a端字段 other['index_a'] = row['index'] other['source_a'] = row['Source'] other['title_a'] = row['Title_new'] # 重命名原有字段为b端 return other.rename(columns={'index':'index_b', 'Source':'source_b', 'Title_new':'title_b'})[['index_a','source_a','title_a','index_b','source_b','title_b']] # 逐行处理后拼接成最终结果 r_df = pd.concat(df.apply(lambda x: pair_row(x, df), axis=1).tolist(), ignore_index=True)
内容的提问来源于stack exchange,提问作者RamaH
相关产品推荐
相关产品推荐

