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

Python金融模型中如何自动将DataFrame多列合并为单一时间序列?

问题说明

我用Python构建了一个金融模型,可输入y个场景(含基准场景)下x年的销售额与利润数据。年度数据按场景存入首个DataFrame(比如x=5且起始年为2022时,基准场景销售额列会包含2022-2026年的数据)。之后我用月度权重生成月度分阶段销售预测,存入新DataFrame,每个年份对应一列(如Base sales 2022、Base sales 2023等)。我需要把这些列合并为单一时间序列(如2022年1月至2026年12月的基准销售额序列),用于图表制作与分析。

我之前用手动添加列名的方式实现过,但这种方法没法适配可变的场景数与年份数,所以尝试自动化处理但没找到可行方案。我没分享主模型代码,而是写了一个示例模型(如下),但代码没法正常运行:虽然输出了创建listA0、listA1、listA2的语句,但这些列表并未实际创建(调用时提示NameError),且输出是多行而非单行。需要解决方案。

示例代码
# 创建场景列表并记录数量
Scenlist=["Bad","Very bad","Terrible"]
Scen_number=3
# 创建评估年份列表并计算年份数量
Years=[2020,2021,2022]
Totyrs=len(Years)
# 创建dprofit数据集,示例中所有列都填充[10,10]

dprofit=pd.DataFrame()
a=0
b=0

# 创建格式为"Bad profit 2020"、"Bad profit 2021"的列名

while a<Scen_number:
  while b<Totyrs:
    dprofit[Scenlist[a]+" profit "+str(Years[b])]=[10,10]
    b=b+1
  b=0
  a=a+1

# 打印生成的表格
print(dprofit)

# 创建新数据集dprofit2,用于将每个场景的年度列合并为完整时间序列
dprofit2=pd.DataFrame()
# 尝试生成代码语句,将dprofit的列合并为listA0、listA1、listA2

a=0
b=0
Totyrs=len(Years)
while a<Scen_number:
   while b<Totyrs:
    if b==0:
      print(f"listA{a}=dprofit['{Scenlist[a]} profit {Years[b]}']")
    else:
      print(f"+dprofit['{Scenlist[a]} profit {Years[b]}']")
    b=b+1
  b=0
  a=a+1
print(listA0)

# 调用print(listA0)会报错:NameError: name 'listA0' is not defined. Did you mean: 'list'?
解决方案

原代码核心问题

  1. 你只是打印了赋值语句的字符串,并没有实际执行这些代码来创建列表,自然会触发NameError。
  2. 循环输出的是多行拼接代码,无法直接作为可执行语句运行。

正确实现方式

不需要通过生成字符串代码的方式,直接用pandas的内置方法就能高效完成场景列的合并,同时适配任意数量的场景和年份:

方法1:用字典存储各场景的合并序列

import pandas as pd

# 初始化场景和年份(和原代码一致)
Scenlist=["Bad","Very bad","Terrible"]
Years=[2020,2021,2022]

# 构建示例dprofit(优化原循环写法)
dprofit = pd.DataFrame()
for scen in Scenlist:
    for year in Years:
        dprofit[f"{scen} profit {year}"] = [10,10]

# 为每个场景合并年度列,存储到字典中
scen_series = {}
for scen in Scenlist:
    # 筛选当前场景的所有年度列
    scen_cols = [col for col in dprofit.columns if col.startswith(f"{scen} profit")]
    # 按年份顺序合并列,转为单一序列
    merged_series = pd.concat([dprofit[col] for col in scen_cols], ignore_index=True)
    scen_series[scen] = merged_series

# 调用示例:获取Bad场景的合并序列
print(scen_series["Bad"])

方法2:直接构建带时间索引的完整时间序列(适配月度数据场景)

如果你的实际需求是生成月度时间序列,可以直接构造日期索引,把年度数据按权重拆分后合并:

import pandas as pd
import numpy as np

# 示例月度权重(假设每年12个月,权重均等)
monthly_weights = np.ones(12)/12

# 初始化场景和年份
Scenlist=["Bad","Very bad","Terrible"]
Years=[2020,2021,2022]

# 构建示例年度利润数据(每个场景每年的年度值)
annual_profit = pd.DataFrame({
    f"{scen} profit {year}": [100] for scen in Scenlist for year in Years
})

# 生成完整月度时间索引
date_index = pd.date_range(start=f"{Years[0]}-01-01", end=f"{Years[-1]}-12-31", freq="MS")

# 为每个场景生成月度序列
dprofit_monthly = pd.DataFrame(index=date_index)
for scen in Scenlist:
    # 提取当前场景的所有年度列
    scen_annual_cols = [col for col in annual_profit.columns if col.startswith(f"{scen} profit")]
    # 按年份顺序拆分年度值为月度数据
    monthly_data = []
    for year in Years:
        annual_value = annual_profit[f"{scen} profit {year}"].iloc[0]
        monthly_data.extend(annual_value * monthly_weights)
    # 添加到结果数据集
    dprofit_monthly[f"{scen} profit monthly"] = monthly_data

# 查看结果
print(dprofit_monthly)

关键优化点

  • 用**列表推导式+pd.concat**替代手动拼接,适配任意数量的场景和年份
  • 避免动态生成代码字符串的危险操作,直接通过pandas API实现逻辑
  • 若需处理月度数据,直接构造时间索引,确保序列的时间连续性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 18:56:01