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

Pandas SettingWithCopy警告及DataFrame修改不生效问题求助

问题描述

Pandas新手(首次使用)开发算法交易回测框架时遇到两个问题:

  1. 触发SettingWithCopyWarning警告;
  2. 在backtest函数中通过df.at修改transactions和wallet列后,返回的DataFrame中这些列仍为NaN,修改未生效。

相关代码与警告输出如下:

原代码

import pandas as pd
import numpy as np
import matplotlib as mpl
import random

def backtest(df):
    # Set wallet properties
    wallet = 1000 # dollars

    # iterate through day by day
    for i in range(len(df)):
        today = df.iloc[i,:]
        print(f"i = {str(i)}")

        signal = random.randint(-1,1)
        print('Signal: ' + str(signal))

        # hold signal
        if signal == 0:
            pass
        # buy signal
        elif signal == 1:
            print('Buying on: ' + str(today['timestamp']) + ' for ' + str(today['close']))
            df.at[i,'transactions'] = 1
            wallet -= today['close']
        # sell signal
        elif signal == -1:
            print('Selling on: ' + str(today['timestamp']) + ' for ' + str(today['close']))
            wallet += today['close']
            df.at[i,'transactions'] = -1
            print(df.at[i,'transactions'])
            print(f"Wallet at ${str(wallet)}")
        df.at[i,'wallet'] = wallet
        print()
    
    return df


# Import the dataset and get it ready to work with
df = pd.read_csv('Data/S&P500_2015-2018.csv')
df['timestamp'] = pd.to_datetime(df['timestamp'])

# Choose which stock(s) you're using
stock = df[df['symbol'] == 'AMD']

out = backtest(stock)
print('All done backtesting')
out.plot(x = 'timestamp', y = 'transactions')

警告输出

i = 0
Signal: 1
Buying on: 2015-12-01 05:00:00+00:00 for 2.34

i = 1
Signal: -1
Selling on: 2015-12-02 05:00:00+00:00 for 2.27
-1.0
Wallet at $999.93

...

i = 398
Signal: -1
Selling on: 2017-06-30 04:00:00+00:00 for 12.48
<ipython-input-10-c0810f02fee9>:25: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  df.loc[i,'transactions'] = 1

问题原因

核心问题是操作了DataFrame的视图而非独立副本:

  • 代码中stock = df[df['symbol'] == 'AMD']是对原DataFrame的切片操作,Pandas返回的是原数据的视图(或潜在副本),而非完全独立的新DataFrame。
  • 当在backtest函数中修改这个对象时,Pandas无法确定你要修改的是原DataFrame还是临时副本,因此抛出SettingWithCopyWarning;同时修改可能仅作用于临时副本,导致最终返回的DataFrame中修改未生效,列仍为NaN。

解决方法

方法1:切片时创建独立副本

在筛选股票时,添加.copy()显式创建独立的DataFrame,后续操作完全独立于原数据:

# 替换原筛选代码
stock = df[df['symbol'] == 'AMD'].copy()

方法2:在函数内部复制传入的DataFrame

如果不想修改外部的筛选逻辑,可以在backtest函数开头复制传入的df,确保操作的是独立副本:

def backtest(df):
    # 新增:复制传入的DataFrame
    df = df.copy()
    wallet = 1000 # dollars
    # 后续代码不变...

额外优化:提前初始化目标列

为避免列初始为NaN的问题,可提前初始化transactions和wallet列:

# 在调用backtest前添加
stock['transactions'] = np.nan
stock['wallet'] = np.nan

修改后的完整代码示例
import pandas as pd
import numpy as np
import matplotlib as mpl
import random

def backtest(df):
    # 复制传入的DataFrame,确保操作独立副本
    df = df.copy()
    wallet = 1000 # dollars
    # 初始化目标列
    df['transactions'] = np.nan
    df['wallet'] = np.nan

    for i in range(len(df)):
        today = df.iloc[i,:]
        print(f"i = {str(i)}")

        signal = random.randint(-1,1)
        print('Signal: ' + str(signal))

        if signal == 0:
            pass
        elif signal == 1:
            print('Buying on: ' + str(today['timestamp']) + ' for ' + str(today['close']))
            df.at[i,'transactions'] = 1
            wallet -= today['close']
        elif signal == -1:
            print('Selling on: ' + str(today['timestamp']) + ' for ' + str(today['close']))
            wallet += today['close']
            df.at[i,'transactions'] = -1
            print(df.at[i,'transactions'])
            print(f"Wallet at ${str(wallet)}")
        df.at[i,'wallet'] = wallet
        print()
    
    return df


df = pd.read_csv('Data/S&P500_2015-2018.csv')
df['timestamp'] = pd.to_datetime(df['timestamp'])

# 筛选时创建独立副本
stock = df[df['symbol'] == 'AMD'].copy()

out = backtest(stock)
print('All done backtesting')
out.plot(x = 'timestamp', y = 'transactions')

内容的提问来源于stack exchange,提问作者Jack Butler

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 08:35:21