Python脚本循环50次仅输出1行,需提取每次迭代的Period字段
问题排查与修复方案
核心问题原因
- 存储结果的代码被放在了
for x in range(50):循环外部,循环执行50次后,只有最后一次生成的df被处理并追加到storage_df,所以最终输出仅1行。 - 每次循环中
df变量会被重新赋值,之前循环生成的df直接被覆盖,无法保留用于后续存储。
修复后的完整代码
import pandas as pd import numpy as np import numpy_financial as npf from datetime import date, datetime from numpy import random # 提前初始化列表,用于收集每次循环的目标数据 results_list = [] for x in range(50): interest=0.04125 years=2 payments_year=12 mortgage=40000 start_date=(date(2023, 2, 1)) initial_pmt = -1 * npf.pmt(interest / 12, years * payments_year, mortgage) initial_ipmt = -1 * npf.ipmt(interest / payments_year, 1, years * payments_year, mortgage) initial_ppmt = -1 * npf.ppmt(interest / payments_year, 1, years * payments_year, mortgage) print(f'第{x+1}次迭代 - Initial Payment: {:,.2f}'.format(initial_pmt)) print(f'第{x+1}次迭代 - Initial Interest: {:,.2f}'.format(initial_ipmt)) print(f'第{x+1}次迭代 - Initial Principal Payment: {:,.2f}'.format(initial_ppmt)) # 创建日期范围 rng = pd.date_range(start_date, periods=years * payments_year, freq='MS') rng.name="Payment Date" # 初始化数据表 df=pd.DataFrame( index=rng, columns= ['Org Total Payment', 'Total Payment', 'Interest', 'Principal', 'Additional Payment', 'Org Ending Balance', 'Ending Balance'], dtype='float') # 设置还款期为索引 df.reset_index(inplace=True) df.index += 1 df.index.name="Period" # 填充第一期数据 period=1 additional_pmt = np.random.randint(2100, 4500, size=len(df)) initial_row_dict = { 'Org Total Payment':initial_pmt, 'Total Payment': initial_pmt + (additional_pmt), 'Interest': initial_ipmt, 'Principal':initial_ppmt, 'Additional Payment': additional_pmt, 'Org Ending Balance': mortgage - initial_ppmt, 'Ending Balance': mortgage - initial_ppmt - (additional_pmt) } columns = list(initial_row_dict.keys()) period_values = list(initial_row_dict.values()) df.at[period, columns]= period_values # 填充后续期数数据 for period in range(2, len(df) + 1): previous_total_payment = df.loc[period - 1, 'Total Payment'] previous_principal = df.loc[period - 1, 'Principal'] previous_org_ending_balance = df.loc[period - 1, 'Org Ending Balance'] previous_ending_balance = df.loc[period - 1, 'Ending Balance'] period_interest = previous_org_ending_balance * interest / payments_year period_principal = initial_pmt - period_interest additional_pmt = np.random.randint(2100, 4500) + 400 org_ending_balance = previous_org_ending_balance - period_principal ending_balance = previous_ending_balance - period_principal - additional_pmt row_dict = {'Org Total Payment':initial_pmt, 'Total Payment': initial_pmt + (additional_pmt), 'Interest': period_interest, 'Principal': period_principal, 'Additional Payment': additional_pmt, 'Org Ending Balance': org_ending_balance, 'Ending Balance': ending_balance} columns = list(row_dict.keys()) period_values = list(row_dict.values()) df.at[period, columns]= period_values # 每次循环内提取当前结果的最后一行Period字段 df_mask=df['Ending Balance']>=0 filtered_df = df[df_mask].round(2) last_row = filtered_df.tail(1) # 仅保留Period列,加入结果列表 results_list.append(last_row[['Period']].reset_index(drop=True)) # 合并所有结果为最终数据表 storage_df = pd.concat(results_list, ignore_index=True) print(storage_df) # 导出CSV时去除无用索引 storage_df.to_csv('allruns.csv', index=False)
关键修改点
- 将结果收集移入循环:每次循环处理完当前
df后,立即提取目标数据并加入列表,避免数据被覆盖。 - 替换append为列表+concat:
pd.DataFrame.append()已被标记为弃用,改用列表收集小数据块后合并,效率更高且符合规范。 - 按需保留字段:仅提取最后一行的
Period字段,满足需求同时减少数据冗余。 - 添加迭代标识:打印信息时加入迭代次数,方便调试观察循环执行状态。
- 优化CSV导出:添加
index=False避免导出的CSV多出无用索引列。
内容的提问来源于stack exchange,提问作者reenum
相关产品推荐
相关产品推荐

