问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

pandas遇到SettingWithCopyWarning警告出现的原因和解决

创作时间:
作者:
@小白创作中心

pandas遇到SettingWithCopyWarning警告出现的原因和解决

引用
CSDN
1.
https://blog.csdn.net/qq_18625571/article/details/139442912

在使用pandas进行数据处理时,经常会遇到SettingWithCopyWarning警告。这个警告通常出现在对DataFrame进行链式操作时,例如在筛选数据后尝试修改数据。本文将详细解释这个警告出现的原因,并提供几种有效的解决方案。

视图和副本的概念

在理解SettingWithCopyWarning之前,我们首先需要区分视图(view)和副本(copy)的概念。

对于 df2 = df.head(3) 来说,df2 为视图,可以理解为截取 df1 的一部分来显示,实际上原数据都是指向 df1。当对视图 df2 进行修改时,会对原数据进行修改。

而对于 df2 = df.head(3).copy()来说,df2df1 截取的一个副本,此处df1df2是两个完全不同的 DataFrame,当对副本 df2 进行修改时,不会修改到 df1。即用 .copy() 实现了数据隔离。

第一种情况:不想在原df上进行修改

如果不想在原df上进行修改,即对由原df得到的新df进行修改希望的同时不影响到原来df的数据,一般使用 .copy(),但是考虑数据量和性能,可以考虑使用 双loc即后面加.loc[:] 从原df获得新df,再对新df进行修改,并且同时不影响原df,实际上是隐式创建副本。

import pandas as pd
ids = [1, 2]
info = {'C': 0.5}
df = pd.DataFrame({
    'id': [1, 2, 3],
    'A': [4, 5, 6],
    'B': [7, 8, 9]
})

# 方法1、使用.copy()显式创建一个新df副本
exp_df = df.loc[df['id'].isin(ids)].copy()
if not exp_df.empty:
    exp_df.loc[:, 'C'] = info['C']
print(exp_df)
print('-------------')
print(df)

# 方法2、使用.loc[:]隐式创建一个新df副本
exp_df = df.loc[df['id'].isin(ids)].loc[:]
if not exp_df.empty:
    exp_df.loc[:, 'C'] = info['C']
print(exp_df)
print('-------------')
print(df)

# 方法3、使用.assign 添加或修改列,并返回一个新的 DataFrame 副本。
exp_df = df.loc[df['id'].isin(ids)].loc[:]
if not exp_df.empty:
    exp_df = exp_df.assign(C=info['C'])
print(exp_df)
print('-------------')
print(df)

第二种情况:想在原df上进行修改

如果想在原df上进行修改(例如使用 drop 或 concat 后重新赋值),即对由原df 得到的新df 进行修改希望同时修改原来df 的数据,则可以使用修改后的df覆盖原df来避免SettingWithCopyWarning警告。

df = pd.DataFrame({
    'id':[1, 2, 3],
    'A': [4, 5, 6],
    'B': [7, 8, 9]
})
df = df.loc[df['id'].isin(ids)]  # 进行覆盖
print(df)
print('---------------')
if not df.empty:
    df.loc[:, 'C'] = 10
print(df)

总结

  1. .copy() 方法用于显式地创建一个 DataFrame 或 Series 的副本,确保数据的独立性,以确保不会在原始数据的副本上进行修改时触发 SettingWithCopyWarning 警告。由于创建完全独立的副本,这意味着所有数据都会被复制一遍,因此在数据量较大的情况下,性能开销(时间、内存消耗)可能会比较大。

  2. 重新赋值操作(例如使用 drop 删除列后重新赋值,或使用 concat 拼接数据后重新赋值)则主要用于数据的更新和变更。这些操作通常会创建一个新的 DataFrame,并将其赋值给原始变量,从而实现数据的变更。这个过程涉及数据的重新构建,时间和内存对消耗依赖于具体对操作和数据量。常用于需要进行数据变更并更新原始 DataFrame 时。

  3. .loc[:] 时,实际上是创建了一个新的 DataFrame 视图,不复制数据,包含所有原始 DataFrame 数据的引用,虽然不像 .copy() 那样创建一个完全独立的副本,但在大多数情况下,对这个新视图的修改也不会影响原始数据,不会触发 SettingWithCopyWarning 警告,但在某些情况(如链式索引可能导致不确定行为)可能会导致意外的修改。常用于需要对筛选后的数据进行修改,但不想显式创建副本时。

总的来说解决SettingWithCopyWarning 警告只有两种方法,第一是创建新df,第二是在原df上修改然后再覆盖原df,只有这两种方式在后续对df修改时才不会报SettingWithCopyWarning。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号