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

加速时间序列自举:优化DataFrame列函数应用速度

时间序列自举样本的函数应用速度优化方案

问题背景

对时间序列执行IID自举生成大量样本后,使用df.apply(func)逐列计算指标的速度成为瓶颈,尤其是样本量超过10000时。部分待应用函数支持DataFrame批量输入,但仍有大量函数仅支持单Series输入,需要针对性优化。


优化方案

1. 优先利用函数的批量处理能力(支持DataFrame输入的场景)

如果目标函数支持直接接收DataFrame作为输入(如示例中的qs.stats.adjusted_sortino),完全不需要使用apply,直接传入整个自举样本DataFrame即可,底层会用向量化逻辑处理,速度远超逐列循环:

# 替代原df_func = df_results.apply(func)
df_func = func(df_results)

2. 并行处理(仅支持单Series输入的场景)

对于不支持批量处理的函数,用多进程/多线程并行处理每一列,充分利用多核CPU资源。以下是基于concurrent.futures的实现:

import concurrent.futures

def process_column(col_series):
    return func(col_series)

# 使用进程池并行处理所有列(CPU密集型场景首选)
with concurrent.futures.ProcessPoolExecutor() as executor:
    results = list(executor.map(process_column, [df_results[col] for col in df_results.columns]))

# 转换为结果Series
df_func = pd.Series(results, index=df_results.columns)

注:若函数为IO密集型,可改用ThreadPoolExecutor。

3. 自举阶段直接计算指标,避免生成大DataFrame(内存+速度双重优化)

原代码先生成包含所有自举样本的大DataFrame再处理,会占用大量内存且增加后续步骤。可以在自举循环中直接计算指标,跳过样本存储环节:

def BootstrapIDD_with_metric(series: pd.Series = None, n_samples: int = 1000, func=None):
    nobs = len(series)
    bsidd = IIDBootstrap(series)
    metric_results = []
    row_range = range(0, nobs)
    
    for pos_data in bsidd.bootstrap(reps=n_samples):
        new_sample = pos_data[0][0]
        new_sample.index = row_range
        # 直接计算当前样本的指标,存入结果列表
        metric_results.append(func(new_sample))
    
    # 生成结果Series
    string_name = series.name
    index = [string_name + '_path_' + str(x) for x in range(1, n_samples + 1)]
    return pd.Series(metric_results, index=index)

# 调用时直接传入目标函数
df_func = BootstrapIDD_with_metric(ret_bench, n_samples=10000, func=func)

该方案大幅减少内存占用(无需存储上万列的DataFrame),同时避免后续apply的循环开销,是最优的端到端优化方案。


内容的提问来源于stack exchange,提问作者msh855

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 14:02:27