如何加速两个大型DataFrame的逐单元格包含性检查?
加速DataFrame单元格内容匹配任务
问题背景
我有两个大型DataFrame,规模分别为125×953和174×808。当前逐单元格检查其中一个DataFrame的内容是否包含另一个DataFrame中的任意词汇,整个过程耗时约30分钟,急需优化提速。
示例DataFrame
参数表(parameter)
color material 0 red wood 1 blue metal 2 green plastic
数据表(data)
name description 0 my blue color it is a great color 1 red chair made with wood 2 green rod made with metal
补充示例数据
# 补充parameter示例 parameter = pd.DataFrame({'color': ['red','blue','green','black','purple'], 'material': ['wood','metal','plastic','','']}) # 补充data示例 data = pd.DataFrame({'name': ['my blue metal color','red chair','green rod',' tree'], 'description': ['it is a great color','made with wood','','']}) data2 = pd.DataFrame({'name': ['my blue metal color ','red chair','green rod',' tree'], 'description': ['it is a great color','made with wood','','']}) # 编辑2补充的示例 parameter = pd.DataFrame({'color': ['red','blue','green','black','purple'], 'material': ['wood','metal','plastic','',''], 'w': ['reed','blue','green','black','purple']},) data = pd.DataFrame({'name': ['my blue metal reed color','red chair','green rod',' tree'], 'description': ['it is a great color','made with wood','',''],})
现有实现代码
import pandas as pd import time data = pd.read_csv('x.csv',converters={i: str for i in range(200)}) parameter = pd.read_excel('y.xlsx', sheet_name="Tags") def extractData(i): for n in i: for row in parameter.columns: print(n.apply(lambda color: [c for c in parameter[row].tolist() if ( str(c)!='nan' and c in color)])) s=time.time() extractData([data[row] for row in data.columns[3:4] ] ) e=time.time() print(e-s)
当前输出结果
name description attribute attribute2 0 my blue color it is a great color blue 1 red chair made with wood red wood 2 green rod made with metal green metal
优化方案
原代码效率低下的核心原因是多层嵌套循环+逐单元格的线性搜索,我们可以通过集合快速查找+pandas矢量化字符串操作来大幅提速:
优化代码实现(列一一对应匹配)
import pandas as pd import time # 读取数据 data = pd.read_csv('x.csv', converters={i: str for i in range(200)}) parameter = pd.read_excel('y.xlsx', sheet_name="Tags") # 预处理:过滤空值并转为集合(集合的in操作是O(1),远快于列表的O(n)) param_sets = {} for col in parameter.columns: # 过滤NaN和空字符串,转为集合 valid_words = parameter[col].dropna().astype(str).str.strip() valid_words = valid_words[valid_words != ''] param_sets[col] = set(valid_words) # 匹配逻辑:parameter的列与data的目标列一一对应匹配 for param_col, data_col in zip(parameter.columns, data.columns[3:4]): # 拆分单元格内容为单词列表,求与参数集合的交集 data[param_col] = data[data_col].str.split() \ .apply(lambda x: ' '.join(param_sets[param_col].intersection(x)) if x else '') # 计时验证 start_time = time.time() # 执行上述匹配逻辑(实际运行时可去掉重复执行) end_time = time.time() print(f"优化后耗时:{end_time - start_time:.2f}秒")
通用匹配逻辑(匹配所有参数词汇)
如果需要让data的每个单元格匹配parameter所有列的词汇,可使用以下代码:
import pandas as pd import time # 读取数据 data = pd.read_csv('x.csv', converters={i: str for i in range(200)}) parameter = pd.read_excel('y.xlsx', sheet_name="Tags") # 合并所有参数列的有效词汇为一个大集合 all_param_words = set() for col in parameter.columns: valid_words = parameter[col].dropna().astype(str).str.strip() valid_words = valid_words[valid_words != ''] all_param_words.update(valid_words) # 对data的目标列进行全参数匹配 for data_col in data.columns[3:4]: data[f'matched_{data_col}'] = data[data_col].str.split() \ .apply(lambda x: ' '.join(all_param_words.intersection(x)) if x else '') # 计时验证 start_time = time.time() # 执行上述匹配逻辑 end_time = time.time() print(f"优化后耗时:{end_time - start_time:.2f}秒")
关键优化点
- 集合替换列表:将参数词汇转为集合,把查找操作的时间复杂度从O(n)降到O(1),大幅减少查找耗时。
- 提前预处理:过滤掉参数中的NaN和空字符串,避免后续循环中重复判断无效值。
- 矢量化操作:利用pandas的
str.split()和apply结合集合交集,替代多层嵌套循环,充分利用pandas的内部优化。 - 减少重复计算:提前生成参数集合,避免每次单元格匹配都重新遍历参数列表。
内容的提问来源于stack exchange,提问作者Shatha Al-Bajly
相关产品推荐
相关产品推荐

