使用df.div和条件填充Pandas DataFrame列值未达预期
问题:正确计算股票拆分后的fractShrs列值
需求是将DataFrame中fractShrs列初始值设为1,当股份数量(numShrs)发生变化时,计算numShrs(t)/numShrs(t+1)作为新的fractShrs值,并保持该值直到下一次股份变化。例如示例中2023-07-06股份从150变为600,fractShrs应从1变为0.25并维持该值。
当前代码及问题
现有代码尝试通过掩码标记股份变化行,但计算结果不符合预期,变化行出现极小值而非目标值:
def populate_fraction_of_shares(df: pd.DataFrame) -> pd.DataFrame: # 创建掩码标记numShrs变化的行 mask = df['numShrs'] != df['numShrs'].shift() # 仅对变化行应用除法 df['fractShrs'] = df['numShrs'].div(df['numShrs'].shift().where(cond=mask, other=1)) # 归一化,使最后一行值为1 df['fractShrs'] = df['fractShrs'].div(df.iloc[-1]['numShrs'])
尝试修改other参数为当前numShrs也未解决问题:
df['fractShrs'] = df['numShrs'].div(df['numShrs'].shift().where(cond=mask, other=df['numShrs']))
示例DataFrame
VWAP VWAPAdj country dividend dividendAdj freeFloatPct numShrs pxAsk pxAskAdj pxBid pxBidAdj pxHigh pxHighAdj pxLast pxLastAdj pxLow pxLowAdj returnIndex turnover volume isin name currency fractShrs date 2023-07-03 176.503682 176.503682 USA 1.00 1.00 94.0 150.00 176.352591 176.352591 176.343429 176.343429 177.644518 177.644518 176.343429 176.343429 175.702037 175.702037 193326.88 5.547447e+09 31458200.0 US0378331005 APPLE INC COM EUR 1 2023-07-05 176.535496 176.535496 USA 1.00 1.00 94.0 150.00 176.292623 176.292623 176.283409 176.283409 177.812933 177.812933 176.292623 176.292623 175.638415 175.638415 192191.75 8.271696e+09 46920262.0 US0378331005 APPLE INC COM EUR 1 2023-07-06 175.203695 175.203695 USA 1.00 1.00 94.0 600.00 176.125087 176.125087 176.106719 176.106719 176.345505 176.345505 176.152638 176.152638 173.755691 173.755691 192673.94 7.954350e+09 45156008.0 US0378331005 APPLE INC COM EUR 1
解决方案
核心思路是计算股份变化点的调整因子,再通过累计乘积得到每个时间点的fractShrs值:
import pandas as pd def populate_fraction_of_shares(df: pd.DataFrame) -> pd.DataFrame: # 复制原DataFrame避免修改原始数据 df = df.copy() # 标记numShrs变化的行,第一行默认标记为变化(初始化) mask = df['numShrs'] != df['numShrs'].shift(fill_value=df['numShrs'].iloc[0]) # 初始化调整因子列,默认值为1(无变化时保持上一因子) df['adjust_factor'] = 1.0 # 在变化行计算调整因子:前一期股份数 / 当前股份数 df.loc[mask, 'adjust_factor'] = df['numShrs'].shift() / df['numShrs'] # 第一行调整因子设为1(初始值) df.loc[df.index[0], 'adjust_factor'] = 1.0 # 累计乘积得到fractShrs,确保变化后的值持续到下一次变化 df['fractShrs'] = df['adjust_factor'].cumprod() # 可选:若需最后一行值为1,执行归一化 # df['fractShrs'] = df['fractShrs'] / df['fractShrs'].iloc[-1] # 删除临时调整因子列 df = df.drop(columns=['adjust_factor']) return df
代码说明
- 掩码标记变化行:通过
shift对比当前与前一期的numShrs,第一行用初始值填充避免NaN。 - 计算调整因子:变化行的因子为
前一期numShrs / 当前numShrs,无变化时因子为1。 - 累计乘积:通过
cumprod()将调整因子累计,确保变化后的fractShrs值持续到下一次股份变化。 - 可选归一化:如果需要最后一行值为1,可取消注释归一化代码。
预期结果
运行后示例DataFrame的fractShrs列值为:
- 2023-07-03: 1
- 2023-07-05: 1
- 2023-07-06: 0.25
内容的提问来源于stack exchange,提问作者Dakolas
相关产品推荐
相关产品推荐

