Pandas无法为DataFrame赋值问题求助
问题描述
我写了一个函数,用来通过对比序列数值和指定最小时长生成周期表格。最近清理开发环境后,同一个函数不再像之前那样给DataFrame赋值,但仍能生成正确形状的DataFrame,找不到问题原因。
之前的输出

当前的输出

代码
from datetime import datetime import pandas as pd pd.options.mode.chained_assignment = None import pandas_datareader.data as web import dataframe_image as dfi # 获取1965年以来联邦基金有效月利率的加息周期 fed_rates = web.DataReader("FEDFUNDS", "fred", 1965) fed_rates.set_index(pd.to_datetime(fed_rates.index.date), inplace=True) # 检测空值 print(fed_rates.index.isna().sum()) def period_df(start, duration, fed_rates=fed_rates): fed_rates = fed_rates[fed_rates.index >= start] df = pd.DataFrame(columns=["Name", "Start", "Last"]) df.loc[df.shape[0]] = [None, None, None] period = 0 j = 0 for i in range(0, len(fed_rates) - 1): if (fed_rates.iloc[i + 1]["FEDFUNDS"] <= fed_rates.iloc[i]["FEDFUNDS"]) and ( i - j >= duration ): df.loc[period]["Last"] = datetime.strftime(fed_rates.index[i], "%Y-%m-%d") period += 1 if (fed_rates.index[-1] - fed_rates.index[i]).days >= 365: df.loc[len(df)] = [None, None, None] j = i elif (fed_rates.iloc[i + 1]["FEDFUNDS"] <= fed_rates.iloc[i]["FEDFUNDS"]) and ( i - j < duration ): df.iloc[period]["Name"] = "Period " + str(period + 1) df.loc[period]["Start"] = datetime.strftime(fed_rates.index[i], "%Y-%m-%d") j = i # 添加最后日期 df.loc[period]["Last"] = datetime.strftime(fed_rates.index[-1], "%Y-%m-%d") # 添加时长列 df["Duration"] = ( pd.to_datetime(df["Last"]) - pd.to_datetime(df["Start"]) ) / np.timedelta64(1, "M") # 将DataFrame导出为图片 dfi.export( df.style.set_properties( **{"background-color": "white", "color": "black", "border-color": "#948b8b"} ), "periods" + start + ".png", ) return df period_df(start="1995", duration=9)
问题分析与解决
1. 缺失依赖导入
原代码使用np.timedelta64但未导入numpy,清理环境后缺少依赖会导致后续赋值逻辑异常,先补上:
import numpy as np
2. 链式索引赋值失效
pandas新版本中,df.loc[period]["Last"] = ...这类链式索引返回的是视图而非副本,即使关闭了链式赋值警告,实际也无法将值写入原DataFrame。需改成单步.loc赋值:
- 替换
df.loc[period]["Last"] = ...为df.loc[period, "Last"] = ... - 替换
df.iloc[period]["Name"] = ...为df.loc[period, "Name"] = ...
3. 动态行赋值的兼容性问题
原代码通过df.loc[len(df)]动态添加行的方式,在pandas新版本中容易引发索引混乱。建议改用列表收集数据后再转DataFrame,避免动态赋值异常:
def period_df(start, duration, fed_rates=fed_rates): fed_rates = fed_rates[fed_rates.index >= start] periods_data = [] current_period = {"Name": None, "Start": None, "Last": None} j = 0 period_count = 0 for i in range(len(fed_rates) - 1): if fed_rates.iloc[i+1]["FEDFUNDS"] <= fed_rates.iloc[i]["FEDFUNDS"]: if i - j >= duration: current_period["Last"] = datetime.strftime(fed_rates.index[i], "%Y-%m-%d") periods_data.append(current_period) if (fed_rates.index[-1] - fed_rates.index[i]).days >= 365: current_period = {"Name": None, "Start": None, "Last": None} j = i period_count += 1 else: current_period["Name"] = f"Period {period_count + 1}" current_period["Start"] = datetime.strftime(fed_rates.index[i], "%Y-%m-%d") j = i # 补充最后一个周期的结束日期 current_period["Last"] = datetime.strftime(fed_rates.index[-1], "%Y-%m-%d") periods_data.append(current_period) df = pd.DataFrame(periods_data) # 计算时长列 df["Duration"] = (pd.to_datetime(df["Last"]) - pd.to_datetime(df["Start"])) / np.timedelta64(1, "M") # 导出图片 dfi.export( df.style.set_properties(**{"background-color": "white", "color": "black", "border-color": "#948b8b"}), f"periods{start}.png" ) return df
4. 版本兼容性
清理环境后pandas版本可能更新,旧版本允许的不规范索引操作在新版本中被严格限制。建议固定依赖版本,或按照pandas官方索引规范修改代码。
内容的提问来源于stack exchange,提问作者gerscorpion
相关产品推荐
相关产品推荐

