You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 18:12:49