对DataFrame每行应用函数生成新列报OutOfBoundsDatetime错误如何解决
根本原因
你调用amortization_table函数时存在传参错误:
函数定义中第二个入参要求的是贷款年限,但你逐行调用时传入的是plazorestanteendias(剩余天数)字段,相当于把3600天直接按照3600年计算,生成的还款日期最远到数千年后,超出了pandas datetime64[ns]类型的支持范围(仅支持1677-09-21 到 2262-04-11之间的日期),因此抛出OutOfBoundsDatetime错误。
解决方案
方案1:修正传参(快速修复)
你已经提前计算了年数字段termy = 剩余天数/360,直接把调用时的第二个参数替换为termy即可:
id_cl['VPInt'] = id_cl.apply(lambda row : amortization_table(row['intrate'], row['termy'], row['lenk'], row['disb']), axis = 1)
方案2:优化函数(推荐,彻底解决问题+提升性能)
由于你最终返回的结果仅用到利息现值总和,完全不需要用到还款日期相关的字段,因此可以直接删掉函数中生成日期序列的逻辑,既不会影响计算结果,还能避免日期越界问题,同时大幅提升运算速度:
def amortization_table(interest_rate, years, payments_year, principal): addl_principal=0 # 直接计算还款期数,去掉所有日期相关逻辑 periods = int(round(years * payments_year, 0)) # 用数字索引替代日期索引 df = pd.DataFrame(index=range(1, periods+1), columns=['Payment', 'Principal', 'Interest', 'Addl_Principal', 'Curr_Balance'], dtype='float') df.index.name = "Period" # 后续计算逻辑保持不变 per_payment = npf.pmt(interest_rate/payments_year, periods, principal) df["Payment"] = per_payment df["Principal"] = npf.ppmt(interest_rate/payments_year, df.index, periods, principal) df["Interest"] = npf.ipmt(interest_rate/payments_year, df.index, periods, principal) df["VP_Interest"] = npf.pv(rate=interest_rate/12, nper = df.index - 1, pmt=0, fv=df["Interest"]) df = df.round(2) # 处理额外还款参数 if addl_principal > 0: addl_principal = -addl_principal df["Addl_Principal"] = addl_principal # 累计本金计算 df["Cumulative_Principal"] = (df["Principal"] + df["Addl_Principal"]).cumsum() df["Cumulative_Principal"] = df["Cumulative_Principal"].clip(lower=-principal) df["Curr_Balance"] = principal + df["Cumulative_Principal"] # 定位最后一期还款 try: last_payment = df.query("Curr_Balance <= 0")["Curr_Balance"].idxmax(axis=1, skipna=True) except ValueError: last_payment = df.last_valid_index() # 有额外还款时截断数据 if addl_principal != 0: df = df.loc[0:last_payment].copy() df.loc[last_payment, "Principal"] = -(df.loc[last_payment-1, "Curr_Balance"]) df.loc[last_payment, "Payment"] = df.loc[last_payment, ["Principal", "Interest"]].sum() df.loc[last_payment, "Addl_Principal"] = 0 # 计算最终返回值 payment_info = df[["VP_Interest"]].sum().to_frame().T cumInt = payment_info.VP_Interest[0]*-1 return cumInt
内容的提问来源于stack exchange,提问作者Daniela saba rosner
相关产品推荐
相关产品推荐

