如何基于pandas DataFrame日期列新增折旧计算列?
解决Pandas按财年折旧计算列值的问题
问题场景
现有Pandas DataFrame包含3列:
Date:字符串格式,形如yyyy-mm-dd-hh-mm-ssABC、XYZ:数值类型
需要新增Target Budget Yield列,计算规则:
- 2019年7月1日至2020年6月30日:取值为50
- 之后每一个财年(当年7月至次年6月),值按15%比例折旧(即乘以0.85)
原代码的问题
原代码存在多处错误,导致出现"ambiguous input"错误、全列值一致或计算结果偏离预期:
- 循环赋值逻辑错误:每次循环都对整个
Target Budget Yield列赋值,最终仅保留最后一次循环的结果,导致全列值统一 - 语法错误:
float5()是笔误(应为float()),且0*属于无效计算(应为50) - 日期类型错误:未将
Date列转为datetime类型,直接用字符串与datetime对象比较,触发"ambiguous input"错误 - 折旧计算逻辑错误:幂次计算不符合财年规则,导致折旧倍数错误
正确解决方案
步骤1:转换Date列为datetime类型
首先将字符串格式的日期转为Pandas可识别的datetime类型,避免比较错误:
import pandas as pd import numpy as np # 转换Date列格式 df['Date'] = pd.to_datetime(df['Date'], format='%Y-%m-%d-%H-%M-%S')
步骤2:按财年计算折旧倍数
基于7月至次年6月的财年规则,计算每个日期对应的折旧次数:
- 2019年7月-2020年6月:折旧次数为0,值为50
- 2020年7月-2021年6月:折旧次数为1,值为50*0.85
- 以此类推
步骤3:批量计算目标列
使用Pandas的向量化操作(避免低效循环)完成计算:
# 定义财年计算逻辑:7月及以后的日期,财年为年份+1;否则为当前年份 df['fiscal_year'] = df['Date'].apply(lambda x: x.year + 1 if x.month >=7 else x.year) # 计算折旧次数:基准财年为2020(对应2019.7-2020.6) df['depreciation_times'] = df['fiscal_year'] - 2020 # 计算目标列值 df['Target Budget Yield'] = 50 * (0.85 ** df['depreciation_times']) # 可选:对2019年7月之前的日期赋值为NaN(若有此类数据) df['Target Budget Yield'] = np.where(df['Date'] < pd.Timestamp('2019-07-01'), np.nan, df['Target Budget Yield'])
简化版(无需额外中间列)
如果不需要保留财年和折旧次数列,可直接用apply一次性计算:
df['Target Budget Yield'] = df['Date'].apply( lambda x: 50 * (0.85 ** ((x.year + 1 if x.month >=7 else x.year) - 2020)) if x >= pd.Timestamp('2019-07-01') else np.nan )
验证结果
- 2019-07-01至2020-06-30:值为50
- 2020-07-01至2021-06-30:值为42.5(50*0.85)
- 2021-07-01至2022-06-30:值为36.125(42.5*0.85)
- 以此类推,符合预期折旧规则
内容的提问来源于stack exchange,提问作者Hatim Jhalodwala
相关产品推荐
相关产品推荐

