You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中高效访问与对比海量股票数据的最优方案

优化方案:从O(n²)到O(n)的高效处理

你的核心需求是对每一行,从当前位置往后查找第一个触发Low<=calc1或High>=calc2的条件,并标记对应结果。原双重循环是**O(n²)**时间复杂度,5千行就需要2500万次操作,百万行完全不可行。下面是几种高效的替代方案:

核心逻辑拆解

对每个位置i,我们只需要知道:

  1. 从i到末尾,第一个满足Low<=calc1的位置(记为last_cond1)
  2. 从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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 21:00:58