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

如何让过滤后的Pandas DataFrame支持按引用更新

问题描述

我通过sell_shares函数过滤DataFrame,代码如下:

def sell_shares(df_company, number_shares, date_end):
    df_filtered = df_company.copy()[(df_company['Date'] <= date_end)]
    df_filtered['Date'] = pd.to_datetime(df_filtered['Date'], dayfirst=True)
    remaining_shares = number_shares # default
    for i, row in df_filtered.iterrows():
        row = df_filtered.iloc[i]
        remaining_shares, df_filtered = remove_shares(df_filtered, i, remaining_shares)

随后调用remove_shares函数并传入df_filtered:

def remove_shares(df, i, number_shares):
    #print("Considering row: ", row)
    print("Before sell, Number of shares: {:}".format(df.iloc[i]["Quantity"]))
    remaining_shares = 0
    if abs(number_shares) < abs(df.iloc[i]["Quantity"]):
        # have less than in batch - so decrement
        #row.columns.set_loc("Quantity") += - abs(number_shares)
        #row["Quantity"] += - abs(number_shares)
        df.iloc[i, df.columns.get_loc("Quantity")] += - abs(number_shares)

我的原始调用函数如下:

def compute_gain_before_tax_year(df, company_name, date_start, date_end):
    df_company = df.copy(deep=True)
    df_company = df_company[df_company["Market"]==company_name]
    df_company = df_company[( df_company["Date"] < pd.to_datetime(date_start, dayfirst=True))]

问题:当我最终执行df.iloc[i, df.columns.get_loc("Quantity")] = 0更新DataFrame时,如何确保所有操作都按引用进行?我在remove_shares函数中能看到本地的修改,但这些修改无法向上传递到上层。

问题分析
  1. DataFrame引用断裂:Pandas DataFrame是引用传递,但如果在函数内执行切片、过滤或copy()操作,会生成新的独立对象,导致上层原对象与修改后的对象断开关联。
  2. 返回逻辑缺失:remove_shares未返回修改后的DataFrame,sell_shares也未将最终修改结果传递给上层调用函数。
  3. 冗余操作:sell_shares中df_filtered = df_company.copy()[(df_company['Date'] <= date_end)]属于冗余操作,先copy再切片会额外生成副本,加剧引用断裂问题。
修复方案

1. 修正sell_shares的对象生成与返回逻辑

避免冗余copy操作,确保返回修改后的DataFrame:

def sell_shares(df_company, number_shares, date_end):
    # 先过滤再copy,减少中间对象生成
    df_filtered = df_company[(df_company['Date'] <= date_end)].copy()
    df_filtered['Date'] = pd.to_datetime(df_filtered['Date'], dayfirst=True)
    remaining_shares = number_shares
    for i, _ in df_filtered.iterrows():
        # 直接传入索引,无需重复获取row
        remaining_shares, df_filtered = remove_shares(df_filtered, i, remaining_shares)
    # 将修改后的DataFrame返回给上层
    return df_filtered

2. 完善remove_shares的业务逻辑与返回

补全卖出逻辑,确保返回修改后的DataFrame和剩余待卖股份数:

def remove_shares(df, i, number_shares):
    current_quantity = abs(df.iloc[i]["Quantity"])
    print("Before sell, Number of shares: {:}".format(current_quantity))
    sell_amount = abs(number_shares)
    
    if sell_amount < current_quantity:
        # 卖出数量小于当前持仓,扣除对应份额
        df.iloc[i, df.columns.get_loc("Quantity")] -= sell_amount
        remaining_shares = 0
    else:
        # 卖出数量大于等于当前持仓,清空该行持仓
        df.iloc[i, df.columns.get_loc("Quantity")] = 0
        remaining_shares = sell_amount - current_quantity
    
    # 返回剩余待卖数和修改后的DataFrame
    return remaining_shares, df

3. 上层函数接收修改结果

在compute_gain_before_tax_year中接收sell_shares返回的修改后DataFrame:

def compute_gain_before_tax_year(df, company_name, number_shares, date_start, date_end):
    df_company = df.copy(deep=True)
    df_company = df_company[df_company["Market"]==company_name]
    df_company = df_company[df_company["Date"] < pd.to_datetime(date_start, dayfirst=True)]
    
    # 接收修改后的DataFrame
    df_company_updated = sell_shares(df_company, number_shares, date_end)
    
    # 后续业务基于修改后的DataFrame处理
    return df_company_updated

关键提示

如果想直接修改传入的原DataFrame而非返回新对象,需避免任何会生成副本的操作(如切片后赋值给新变量),但Pandas的视图/副本规则较复杂,明确返回修改后的DataFrame是更稳妥、易维护的方式。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 17:17:48