股票数据分析优化请求:60万行数据组合过滤提速方案
股票数据分析代码优化方案
问题背景
你正在处理60万行的股票数据,生成了最多包含20个条件的所有组合,现在需要过滤这些组合并统计盈利场景占比,但当前Python代码运行耗时过长,急需优化。
现有代码的核心性能瓶颈
- 重复计算冗余:每次循环处理一个条件组合时,都要重新对整个60万行数据进行筛选操作,相同条件的筛选被重复执行了无数次,这是最大的性能浪费。
- 频繁IO操作:每处理一个组合就打开一次结果文件追加写入,磁盘IO本身速度较慢,频繁的打开/关闭会大幅拖慢整体速度。
- 不必要的DataFrame切片:每次循环都复制并切片DataFrame,切片操作会占用额外内存且耗时,其实我们只需要统计行数,不需要实际生成子集DataFrame。
- 逻辑小bug:代码中
dfTemp=dfTemp[dfData[col_name].str.contains(col_name)]使用了原数据dfData而非当前子集dfTemp,这会导致筛选逻辑错误,同时也影响性能。
具体优化方案
1. 预计算所有条件的筛选掩码
提前为每个条件计算好布尔掩码(满足条件的行标记为True,否则为False),存储在字典中。后续处理组合时,直接复用这些掩码,避免重复计算。
2. 批量处理结果,减少IO操作
先把所有组合的计算结果存储在内存列表中,最后一次性写入结果文件,彻底避免频繁的磁盘IO。
3. 用布尔数组运算替代DataFrame切片
利用numpy的向量化布尔运算,直接对掩码进行逻辑与操作,统计符合条件的行数,不需要生成中间DataFrame,大幅节省内存和时间。
4. 优化占位符AAA的处理
组合中的AAA是无效条件,直接过滤掉即可,不需要在原数据中添加额外列。
优化后的示例代码
import pandas as pd import numpy as np # 输入文件路径 dataFile = "ReferenceFile.txt" combinationFile = "Combination.csv" ResultFile = "Result.csv" # 读取数据文件 dfData = pd.read_csv(dataFile, sep=",") dfData.fillna("", inplace=True) # -------------------------- # 预计算所有条件的掩码(核心优化点) # -------------------------- # 获取所有有效条件(排除AAA,因为我们不需要处理它) valid_conditions = [col for col in dfData.columns if col != "AAA"] # 存储每个条件的筛选掩码:key=条件名称,value=布尔数组(满足条件的行) condition_masks = {} # 存储每个条件下盈利的掩码:满足条件且盈利的行 profit_masks = {} for cond in valid_conditions: # 计算该条件的基础掩码 cond_mask = dfData[cond].str.contains(cond) condition_masks[cond] = cond_mask # 计算满足条件且盈利的掩码 profit_masks[cond] = cond_mask & dfData[cond].str.contains("Profit") # -------------------------- # 处理所有条件组合 # -------------------------- results = [] # 读取组合文件 with open(combinationFile, "r") as comb_file: for line in comb_file: # 处理每行组合:去掉换行符,拆分条件,过滤掉AAA line = line.strip() if not line: continue combo_conds = [cond.strip() for cond in line.split(',') if cond.strip() != "AAA"] # 初始化总掩码:全True表示所有行都符合(无有效条件时直接用全量数据) total_mask = np.ones(len(dfData), dtype=bool) profit_total_mask = np.ones(len(dfData), dtype=bool) # 组合所有有效条件的掩码 for cond in combo_conds: total_mask &= condition_masks[cond] profit_total_mask &= profit_masks[cond] # 统计数量 total_count = total_mask.sum() profit_count = profit_total_mask.sum() # 构建结果字符串 cond_str = "|".join(combo_conds) if combo_conds else "" results.append(f"{total_count}|{profit_count}|{cond_str}\n") # -------------------------- # 一次性写入结果文件 # -------------------------- with open(ResultFile, "w") as result_file: result_file.writelines(results) print("Complete")
额外优化建议
- 并行处理:如果条件组合数量极大(比如超过100万),可以使用
multiprocessing模块将组合拆分到多个进程并行处理,进一步缩短时间。 - 内存优化:如果60万行数据占用内存过高,可以考虑用
dask.dataframe替代pandas进行分块处理,但需要调整掩码的计算逻辑。 - 字符串匹配优化:如果
str.contains是性能瓶颈,可以提前将列转换为分类数据,或者用==替代contains(如果条件匹配是精确匹配的话)。
内容的提问来源于stack exchange,提问作者Ed George
相关产品推荐
相关产品推荐

