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

Pandas SettingWithCopyWarning成因及apply与astype选型咨询

问题分析与解答

先看你的代码和数据源:

示例代码

import pandas as pd
import numpy as np
pd.set_option('display.expand_frame_repr', False)
foo = pd.read_csv("foo2.csv", skipinitialspace=True, index_col='Index')
foo.loc[:, 'Date'] = pd.to_datetime(foo.Date)
for i in range(0, len(foo)-1):
    if foo.at[i, 'Type'] == 'Reservation':
        for j in range(i+1, len(foo)):
            if foo.at[j, 'Type'] == 'Payout':
                foo.at[j, 'Nights'] = foo.at[i, 'Nights']
                break
mask = (foo['Date'] >= '2018-03-31') & (foo['Date'] <= '2019-03-31')
foo2019 = foo.loc[mask]
foopayouts2019 = foo2019.loc[foo2019['Type'] == 'Payout']
foopayouts2019.loc[:, 'Nights'] = foopayouts2019['Nights'].apply(np.int64)
# foopayouts2019.loc[:, 'Nights'] = foopayouts2019['Nights'].astype(np.int64, copy=False)

数据源(foo2.csv)

Index,Date,Type,Nights,Amount,Payout
0,03/07/2018,Reservation,2.0,1000.00,
1,03/07/2018,Payout,,,1000.00
2,09/11/2018,Reservation,3.0,1500.00,
3,09/11/2018,Payout,,,1500.00
4,02/16/2019,Reservation,2.0,2000.00,
5,02/16/2019,Payout,,,2000.00
6,04/25/2019,Reservation,7.0,1200.00,
7,04/25/2019,Payout,,,1200.00

1. SettingWithCopyWarning的成因是什么?已使用.loc,是否是更早代码逻辑导致?

没错,问题确实出在更早的切片逻辑上,和你最后用不用.loc关系不大。

当你执行foo2019 = foo.loc[mask]和foopayouts2019 = foo2019.loc[foo2019['Type'] == 'Payout']时,这两个变量都是原DataFramefoo的视图(view),而非独立的副本(copy)。Pandas的切片默认会尽量返回视图以节省内存,但这就导致后续你对foopayouts2019做修改时,Pandas无法确定你是想修改原数据foo,还是只想修改这个切片后的临时对象,因此抛出警告。

解决方法很简单,在创建切片时显式添加.copy(),强制生成独立副本:

foo2019 = foo.loc[mask].copy()
foopayouts2019 = foo2019.loc[foo2019['Type'] == 'Payout'].copy()

这样后续修改foopayouts2019就不会触发警告了。

2. 数据类型转换时,apply(np.int64)与astype(np.int64, copy=False)哪种方案更优?

毫无疑问,astype(np.int64, copy=False)是更优的选择,原因有两点:

  • 效率更高:astype是Pandas针对整个Series的向量化操作,底层用C实现,处理速度远快于apply。apply本质是逐元素遍历执行函数,相当于Python层面的循环,数据量越大,效率差距越明显。
  • 内存控制更灵活:copy=False参数会让Pandas尝试在原内存块上直接修改数据(如果数据类型转换允许的话),避免不必要的内存拷贝。而apply一定会生成新的Series,无法做到这一点。

另外要注意:如果你的Nights列存在缺失值(NaN),转int64会报错,因为整数类型无法存储NaN。不过从你的数据源来看,这列数据都是有效的数值,所以没问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:32:46