Python中高效访问与对比海量股票数据的最优方案
优化方案:从O(n²)到O(n)的高效处理
你的核心需求是对每一行,从当前位置往后查找第一个触发Low<=calc1或High>=calc2的条件,并标记对应结果。原双重循环是**O(n²)**时间复杂度,5千行就需要2500万次操作,百万行完全不可行。下面是几种高效的替代方案:
核心逻辑拆解
对每个位置i,我们只需要知道:
- 从
i到末尾,第一个满足Low<=calc1的位置(记为last_cond1) - 从
i到末尾,第一个满足High>=calc2的位置(记为last_cond2)
然后比较两者的先后顺序:
- 若
last_cond1存在且早于/等于last_cond2→ 标记message1 - 若
last_cond2存在 → 标记message2 - 否则 → 标记
message3
通过反向遍历可以在O(n)时间内计算出所有位置的last_cond1和last_cond2,这是效率提升的关键。
Python/Numpy 高效实现
Numpy的数组操作比Pandas的行级访问快得多,结合单循环(反向遍历),百万级数据可秒级处理:
import numpy as np import pandas as pd df = pd.read_csv('data.csv') calc1 = 1 # 替换为你的实际计算值 calc2 = 2 # 替换为你的实际计算值 # 生成布尔条件数组(numpy格式) cond1 = df['Low'].values <= calc1 cond2 = df['High'].values >= calc2 n_rows = len(df) # 初始化数组,用无穷大表示"未找到" last_cond1 = np.full(n_rows, np.inf) last_cond2 = np.full(n_rows, np.inf) # 反向遍历,记录每个位置往后最近的满足条件的索引 for i in range(n_rows-1, -1, -1): # 更新last_cond1:当前行满足则记录,否则继承下一行的结果 if cond1[i]: last_cond1[i] = i elif i < n_rows - 1: last_cond1[i] = last_cond1[i+1] # 更新last_cond2:逻辑同上 if cond2[i]: last_cond2[i] = i elif i < n_rows - 1: last_cond2[i] = last_cond2[i+1] # 生成最终标记结果 notes = np.full(n_rows, 'message3', dtype='U20') # 先标记message1:存在满足条件且优先级更高 mask1 = (last_cond1 != np.inf) & (last_cond1 <= last_cond2) notes[mask1] = 'message1' # 再标记message2:存在满足条件且未被message1覆盖 mask2 = (last_cond2 != np.inf) & ~mask1 notes[mask2] = 'message2' # 将结果赋值回DataFrame df['notes'] = notes
Pandas 向量化替代写法
如果更习惯Pandas语法,可以用shift和累积操作实现反向遍历逻辑,效率略低于numpy但远胜双重循环:
import pandas as pd df = pd.read_csv('data.csv') calc1 = 1 calc2 = 2 # 生成条件列 df['cond1'] = df['Low'] <= calc1 df['cond2'] = df['High'] >= calc2 # 反向计算最近的满足条件的位置 df['last_cond1'] = df.index.where(df['cond1']).bfill() df['last_cond2'] = df.index.where(df['cond2']).bfill() # 生成标记 df['notes'] = 'message3' df.loc[(df['last_cond1'].notna()) & (df['last_cond1'] <= df['last_cond2']), 'notes'] = 'message1' df.loc[(df['last_cond2'].notna()) & (df['notes'] == 'message3'), 'notes'] = 'message2' # 清理临时列 df.drop(['cond1', 'cond2', 'last_cond1', 'last_cond2'], axis=1, inplace=True)
其他工具方案
- R + data.table:data.table的反向累积和窗口函数非常适合这类操作,语法简洁且性能优异。核心逻辑和Python一致,用反向遍历记录最近满足条件的位置,再生成标记。
- MongoDB:如果数据量突破千万级,可考虑将数据导入MongoDB,利用其聚合管道的窗口函数(MongoDB 5.0+支持)实现类似逻辑,适合分布式处理场景。但百万级数据用Python/numpy已足够高效,无需额外引入数据库。
内容的提问来源于stack exchange,提问作者Ammo
相关产品推荐
相关产品推荐

