请求优化检测DataFrame列差异的Python低效函数
优化DataFrame列对差异检测函数
问题背景
需要检测DataFrame中指定列对的差异,为每行生成记录差异对应标识的列表,但原函数采用逐行遍历的实现方式,运行效率低下。
DataFrame结构示例:
1 2 3 4 ... 19 20 ------------------------ foo Fou bar bar ... noob noob1
原函数代码:
def find_changes_in_cols(df): df['Change_Info'] = '' for i in range(len(df)): liste = [] if df.at[i, '1'] != df.at[i, '2']: liste.append('Downlink') if df.at[i, '3'] != df.at[i, '4']: liste.append('Uplink') if df.at[i, '5'] != df.at[i, '6']: liste.append('Inp') if df.at[i, '7'] != df.at[i, '8']: liste.append('Power') if df.at[i, '9'] != df.at[i, '10']: liste.append('SNR') if df.at[i, '11'] != df.at[i, '12']: liste.append('RFI') if df.at[i, '13'] != df.at[i, '14']: liste.append('UPBO') if df.at[i, '15'] != df.at[i, '16']: liste.append('DPBO') if df.at[i, '17'] != df.at[i, '18']: liste.append('VN') if df.at[i, '19'] != df.at[i, '20']: liste.append('Vect') df.at[i, 'Change_Info'] = liste return df
原函数输出示例:
1 2 3 4 ... 19 20 Change_Info ------------------------ foo Fou bar bar ... noob noob1 [Downlink, Vect]
优化方案
利用Pandas的矢量化操作替代逐行循环,大幅提升运行效率,同时增强代码可维护性。
基础优化版
import pandas as pd def find_changes_in_cols_optimized(df): # 集中定义列对与对应标识的映射,便于后续修改维护 column_pairs = [ ('1', '2', 'Downlink'), ('3', '4', 'Uplink'), ('5', '6', 'Inp'), ('7', '8', 'Power'), ('9', '10', 'SNR'), ('11', '12', 'RFI'), ('13', '14', 'UPBO'), ('15', '16', 'DPBO'), ('17', '18', 'VN'), ('19', '20', 'Vect'), ] # 为每个列对生成差异标记列(差异时为对应标识,否则为None) change_cols = [] for col1, col2, label in column_pairs: mask = df[col1] != df[col2] change_cols.append(mask.map(lambda x: label if x else None)) # 按行合并所有标记列,过滤掉None值得到最终差异列表 df['Change_Info'] = pd.concat(change_cols, axis=1).apply( lambda row: [item for item in row if item is not None], axis=1 ) return df
优化说明
- 矢量化运算:避免了
df.at逐行访问的低效操作,通过列级批量处理所有行,在数据量较大时性能提升显著。 - 可维护性:列对与标识的映射集中管理,新增或修改规则只需调整
column_pairs列表,无需修改大量重复判断。
超大数据集终极优化版
如果处理百万级以上行的数据集,apply(axis=1)仍有性能瓶颈,可直接操作NumPy数组进一步提速:
def find_changes_in_cols_ultimate(df): column_pairs = [ ('1', '2', 'Downlink'), ('3', '4', 'Uplink'), ('5', '6', 'Inp'), ('7', '8', 'Power'), ('9', '10', 'SNR'), ('11', '12', 'RFI'), ('13', '14', 'UPBO'), ('15', '16', 'DPBO'), ('17', '18', 'VN'), ('19', '20', 'Vect'), ] # 预先计算所有列对的差异掩码(NumPy数组) masks = [(df[col1] != df[col2]).values for col1, col2, _ in column_pairs] labels = [label for _, _, label in column_pairs] # 用列表推导逐行生成结果,避开Pandas apply的额外开销 df['Change_Info'] = [ [labels[j] for j in range(len(masks)) if masks[j][i]] for i in range(len(df)) ] return df
内容的提问来源于stack exchange,提问作者kopsman
相关产品推荐
相关产品推荐

