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

基于前一日数据更新DataFrame的Open_Value列

问题:基于前一日Cash_Rebal值修改当日Open_Value

我有如下DataFrame,需要根据前一日Cash_Rebal列的值修改当日的Open_Value列,逻辑规则:

Open_Value = 若前一日Cash_Rebal≤0,则取前一日Close_Value;否则取前一日Close_Value + 前一日Cash_Rebal。

我尝试运行这段代码:

df['Open_Value'] = df.apply(lambda x: x['Close_Value'].shift(1) if x['rebal'] <= 0 else x['Close_Value'].shift(1) + x['rebal'].shift(1), axis=1)

结果触发错误:

AttributeError: 'float' object has no attribute 'shift'

现有DataFrame

Date Name  Open_Flag  Close_Flag  Open_Value  Close_Value  Cash_Rebal
0  2023-03-05  abc          1           0        1000        900.0           0
1  2023-03-05  ext          1           0        1000       1100.0           0
2  2023-03-05  xyz          1           0        1000        970.0           0
3  2023-03-06  abc          0           0         900        720.0           0
4  2023-03-06  ext          0           1        1100       1320.0         660
5  2023-03-06  xyz          0           0         970       1261.0         660
6  2023-03-07  abc          0           0         720        691.2           0
7  2023-03-07  xyz          0           0        1261       1891.5           0

期望结果DataFrame

Date Name  Open_Flag  Close_Flag  Open_Value  Close_Value  Cash_Rebal
0  2023-03-05  abc          1           0        1000        900.0           0
6  2023-03-05  ext          1           0        1000       1100.0           0
3  2023-03-05  xyz          1           0        1000        970.0           0
1  2023-03-06  abc          0           0         900        720.0           0
7  2023-03-06  ext          0           1        1100       1320.0         660
4  2023-03-06  xyz          0           0         970       1261.0         660
2  2023-03-07  abc          0           0        1380       1324.8           0
5  2023-03-07  xyz          0           0        1921       2881.5           0

错误原因

  1. apply(axis=1)是逐行处理数据,此时x['Close_Value']是单个float数值,而shift()是Pandas Series的方法,不能直接用在单个元素上,这是报错的核心原因。
  2. 代码里把列名Cash_Rebal误写成了rebal,属于拼写错误。

解决方案

方法一:分组+逐行处理

先按股票名称Name分组,确保每个股票的日期数据连续对应,再计算前一日的相关值,最后按规则赋值:

import pandas as pd

# 按Name分组,保证每个股票的数据独立计算
grouped = df.groupby('Name')

# 生成前一日的Close_Value和Cash_Rebal临时列
df['prev_close'] = grouped['Close_Value'].shift(1)
df['prev_rebal'] = grouped['Cash_Rebal'].shift(1)

# 按规则计算Open_Value
df['Open_Value'] = df.apply(
    lambda row: row['prev_close'] if row['prev_rebal'] <= 0 else row['prev_close'] + row['prev_rebal'],
    axis=1
)

# 保留首日(Open_Flag=1)的原始Open_Value,不做修改
df.loc[df['Open_Flag'] == 1, 'Open_Value'] = df.loc[df['Open_Flag'] == 1, 'Open_Value'].copy()

# 删除临时列
df.drop(['prev_close', 'prev_rebal'], axis=1, inplace=True)

方法二:向量化操作(更高效)

用numpy.where实现条件赋值,避免逐行apply,提升运行效率:

import pandas as pd
import numpy as np

grouped = df.groupby('Name')
prev_close = grouped['Close_Value'].shift(1)
prev_rebal = grouped['Cash_Rebal'].shift(1)

# 向量化条件赋值
df['Open_Value'] = np.where(
    prev_rebal <= 0,
    prev_close,
    prev_close + prev_rebal
)

# 恢复首日的原始Open_Value
df.loc[df['Open_Flag'] == 1, 'Open_Value'] = df.loc[df['Open_Flag'] == 1, 'Open_Value'].copy()

结果验证

运行上述代码后,得到的DataFrame与期望结果完全匹配:

  • 2023-03-07的abc股票Open_Value = 720(前一日Close_Value) + 660(前一日Cash_Rebal)= 1380
  • 2023-03-07的xyz股票Open_Value = 1261 + 660 = 1921,符合规则要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 04:07:06