如何处理熊猫设置与复制警告

背景

我刚刚将我的熊猫从0.11升级到0.13.0rc1。现在,应用程序弹出了许多新的警告。其中一个像这样:

E:\FinReporter\FM_EXT.py:449: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.Try using .loc[row_index,col_indexer] = value insteadquote_df['TVol']   = quote_df['TVol']/TVOL_SCALE

我想知道这到底是什么意思?我需要改变什么吗?

如果我坚持使用quote_df['TVol'] = quote_df['TVol']/TVOL_SCALE,我应该如何暂停警告?

给出错误的函数

def _decode_stock_quote(list_of_150_stk_str):"""decode the webpage and return dataframe"""
from cStringIO import StringIO
str_of_all = "".join(list_of_150_stk_str)
quote_df = pd.read_csv(StringIO(str_of_all), sep=',', names=list('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefg')) #dtype={'A': object, 'B': object, 'C': np.float64}quote_df.rename(columns={'A':'STK', 'B':'TOpen', 'C':'TPCLOSE', 'D':'TPrice', 'E':'THigh', 'F':'TLow', 'I':'TVol', 'J':'TAmt', 'e':'TDate', 'f':'TTime'}, inplace=True)quote_df = quote_df.ix[:,[0,3,2,1,4,5,8,9,30,31]]quote_df['TClose'] = quote_df['TPrice']quote_df['RT']     = 100 * (quote_df['TPrice']/quote_df['TPCLOSE'] - 1)quote_df['TVol']   = quote_df['TVol']/TVOL_SCALEquote_df['TAmt']   = quote_df['TAmt']/TAMT_SCALEquote_df['STK_ID'] = quote_df['STK'].str.slice(13,19)quote_df['STK_Name'] = quote_df['STK'].str.slice(21,30)#.decode('gb2312')quote_df['TDate']  = quote_df.TDate.map(lambda x: x[0:4]+x[5:7]+x[8:10])    
return quote_df

更多错误消息

E:\FinReporter\FM_EXT.py:449: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.Try using .loc[row_index,col_indexer] = value insteadquote_df['TVol']   = quote_df['TVol']/TVOL_SCALEE:\FinReporter\FM_EXT.py:450: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.Try using .loc[row_index,col_indexer] = value insteadquote_df['TAmt']   = quote_df['TAmt']/TAMT_SCALEE:\FinReporter\FM_EXT.py:453: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.Try using .loc[row_index,col_indexer] = value insteadquote_df['TDate']  = quote_df.TDate.map(lambda x: x[0:4]+x[5:7]+x[8:10])
1787584 次浏览

创建SettingWithCopyWarning是为了标记可能令人困惑的“链式”分配,例如以下内容,它并不总是按预期工作,特别是当第一个选择返回复制时。

df[df['A'] > 2]['B'] = new_val  # new_val not set in df

该警告建议重写如下:

df.loc[df['A'] > 2, 'B'] = new_val

但是,这不适合您的用法,相当于:

df = df[df['A'] > 2]df['B'] = new_val

虽然很明显你不关心写入是否使其返回原始帧(因为你正在覆盖对它的引用),但不幸的是,这种模式无法与第一个链式赋值示例区分开来。因此有(误报)警告。如果你想进一步阅读,误报的可能性在索引开发文档中得到了解决。你可以通过以下赋值安全地禁用这个新警告。

import pandas as pdpd.options.mode.chained_assignment = None  # default='warn'

其他资源

一般来说,SettingWithCopyWarning的目的是向用户(尤其是新用户)展示他们可能是在操作副本,而不是他们认为的原始版本。有误报(IOW,如果你知道自己在做什么,可能是好的)。一种可能性是像@Garrett建议的那样简单地关闭(默认情况下警告)警告。

这里有另一种选择:

In [1]: df = DataFrame(np.random.randn(5, 2), columns=list('AB'))
In [2]: dfa = df.ix[:, [1, 0]]
In [3]: dfa.is_copyOut[3]: True
In [4]: dfa['A'] /= 2/usr/local/bin/ipython:1: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.Try using .loc[row_index,col_indexer] = value instead#!/usr/local/bin/python

您可以将is_copy标志设置为False,这将有效地关闭检查,对于该对象

In [5]: dfa.is_copy = False
In [6]: dfa['A'] /= 2

如果您显式复制,则不会发生进一步的警告:

In [7]: dfa = df.ix[:, [1, 0]].copy()
In [8]: dfa['A'] /= 2

OP上面显示的代码虽然合法,可能我也做了一些事情,但从技术上讲是此警告的案例,而不是误报。没有获得警告的另一种方法是通过reindex执行选择操作,例如:

quote_df = quote_df.reindex(columns=['STK', ...])

或者,

quote_df = quote_df.reindex(['STK', ...], axis=1)  # v.0.21

熊猫数据框复制警告

当你去做这样的事情时:

quote_df = quote_df.ix[:,[0,3,2,1,4,5,8,9,30,31]]

pandas.ix在这种情况下返回一个新的独立数据帧。

您决定在此数据框中更改的任何值都不会更改原始数据框。

这就是熊猫试图警告你的。


为什么.ix是个坏主意

.ix对象尝试做不止一件事,对于任何读过干净代码的人来说,这是一个强烈的气味。

给定这个数据框:

df = pd.DataFrame({"a": [1,2,3,4], "b": [1,1,2,2]})

两种行为:

dfcopy = df.ix[:,["a"]]dfcopy.a.ix[0] = 2

行为一:dfcopy现在是一个独立的数据框。更改它不会更改df

df.ix[0, "a"] = 3

行为二:这会改变原始数据框。


使用.loc代替

熊猫开发人员意识到.ix对象很臭[推测],因此创建了两个新对象,这有助于数据的访问和分配。(另一个是.iloc

.loc更快,因为它不会尝试创建数据的副本。

.loc旨在就地修改现有的数据框,这更有效地节省内存。

.loc是可预测的,它有一个行为。


的解决方案

您在代码示例中所做的是加载一个包含大量列的大文件,然后将其修改为更小。

pd.read_csv函数可以帮助您解决很多问题,并使文件的加载速度更快。

所以与其这样做

quote_df = pd.read_csv(StringIO(str_of_all), sep=',', names=list('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefg')) #dtype={'A': object, 'B': object, 'C': np.float64}quote_df.rename(columns={'A':'STK', 'B':'TOpen', 'C':'TPCLOSE', 'D':'TPrice', 'E':'THigh', 'F':'TLow', 'I':'TVol', 'J':'TAmt', 'e':'TDate', 'f':'TTime'}, inplace=True)quote_df = quote_df.ix[:,[0,3,2,1,4,5,8,9,30,31]]

做这个

columns = ['STK', 'TPrice', 'TPCLOSE', 'TOpen', 'THigh', 'TLow', 'TVol', 'TAmt', 'TDate', 'TTime']df = pd.read_csv(StringIO(str_of_all), sep=',', usecols=[0,3,2,1,4,5,8,9,30,31])df.columns = columns

这只会读取您感兴趣的列,并正确命名它们。不需要使用邪恶的.ix对象来做神奇的事情。

如果您已将切片分配给变量并希望使用该变量进行设置,如下所示:

df2 = df[df['A'] > 2]df2['B'] = value

并且您不想使用杰夫的解决方案,因为您的条件计算df2很长或出于其他原因,那么您可以使用以下内容:

df.loc[df2.index.tolist(), 'B'] = value

df2.index.tolist()返回df2中所有条目的索引,然后将用于设置原始数据帧中的列B。

为了消除任何疑问,我的解决方案是制作切片的深度副本而不是常规副本。这可能不适用,具体取决于您的上下文(内存约束/切片大小,性能下降的可能性-特别是如果复制发生在像我这样的循环中,等等…)

需要说明的是,以下是我收到的警告:

/opt/anaconda3/lib/python3.6/site-packages/ipykernel/__main__.py:54:SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrameSee the caveats in the documentation:http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy

插图

我怀疑发出警告是因为我在切片的副本上放置了一列。虽然从技术上讲没有试图在切片的副本中设置值,但这仍然是对切片副本的修改。

以下是我为证实怀疑而采取的(简化)步骤,我希望它能帮助我们这些试图理解警告的人。

示例1:在原始上删除一列会影响副本

我们已经知道了,但这是一个健康的提醒。这是不是警告的内容。

>> data1 = {'A': [111, 112, 113], 'B':[121, 122, 123]}>> df1 = pd.DataFrame(data1)>> df1
A    B0    111    1211    112    1222    113    123

>> df2 = df1>> df2
A    B0    111    1211    112    1222    113    123
# Dropping a column on df1 affects df2>> df1.drop('A', axis=1, inplace=True)>> df2B0    1211    1222    123

可以避免在df1上所做的更改影响df2。注意:您可以通过执行df.copy()来避免导入copy.deepcopy

>> data1 = {'A': [111, 112, 113], 'B':[121, 122, 123]}>> df1 = pd.DataFrame(data1)>> df1
A    B0    111    1211    112    1222    113    123
>> import copy>> df2 = copy.deepcopy(df1)>> df2A    B0    111    1211    112    1222    113    123
# Dropping a column on df1 does not affect df2>> df1.drop('A', axis=1, inplace=True)>> df2A    B0    111    1211    112    1222    113    123

示例2:在副本上删除一列可能会影响原始

这实际上说明了警告。

>> data1 = {'A': [111, 112, 113], 'B':[121, 122, 123]}>> df1 = pd.DataFrame(data1)>> df1
A    B0    111    1211    112    1222    113    123
>> df2 = df1>> df2
A    B0    111    1211    112    1222    113    123
# Dropping a column on df2 can affect df1# No slice involved here, but I believe the principle remains the same?# Let me know if not>> df2.drop('A', axis=1, inplace=True)>> df1
B0    1211    1222    123

可以避免在df2上所做的更改影响df1

>> data1 = {'A': [111, 112, 113], 'B':[121, 122, 123]}>> df1 = pd.DataFrame(data1)>> df1
A    B0    111    1211    112    1222    113    123
>> import copy>> df2 = copy.deepcopy(df1)>> df2
A    B0    111    1211    112    1222    113    123
>> df2.drop('A', axis=1, inplace=True)>> df1
A    B0    111    1211    112    1222    113    123

你可以像这样避免整个问题,我相信:

return (pd.read_csv(StringIO(str_of_all), sep=',', names=list('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefg')) #dtype={'A': object, 'B': object, 'C': np.float64}.rename(columns={'A':'STK', 'B':'TOpen', 'C':'TPCLOSE', 'D':'TPrice', 'E':'THigh', 'F':'TLow', 'I':'TVol', 'J':'TAmt', 'e':'TDate', 'f':'TTime'}, inplace=True).ix[:,[0,3,2,1,4,5,8,9,30,31]].assign(TClose=lambda df: df['TPrice'],RT=lambda df: 100 * (df['TPrice']/quote_df['TPCLOSE'] - 1),TVol=lambda df: df['TVol']/TVOL_SCALE,TAmt=lambda df: df['TAmt']/TAMT_SCALE,STK_ID=lambda df: df['STK'].str.slice(13,19),STK_Name=lambda df: df['STK'].str.slice(21,30)#.decode('gb2312'),TDate=lambda df: df.TDate.map(lambda x: x[0:4]+x[5:7]+x[8:10]),))

使用分配。从留档:将新列分配给DataFrame,返回一个新对象(副本),其中包含除新列之外的所有原始列。

参见Tom Augspurger关于方法链接的文章:现代熊猫(第2部分):方法链

对我来说,这个问题发生在以下简化示例中。我也能够解决它(希望有正确的解决方案):

带有警告的旧代码:

def update_old_dataframe(old_dataframe, new_dataframe):for new_index, new_row in new_dataframe.iterrorws():old_dataframe.loc[new_index] = update_row(old_dataframe.loc[new_index], new_row)
def update_row(old_row, new_row):for field in [list_of_columns]:# line with warning because of chain indexing old_dataframe[new_index][field]old_row[field] = new_row[field]return old_row

这打印了行old_row[field] = new_row[field]的警告

由于update_row方法中的行实际上是类型Series,我将该行替换为:

old_row.at[field] = new_row.at[field]

即,一种方法用于访问/查找Series。即使两者都工作得很好并且结果相同,这样我就不必禁用警告(=将它们保留在其他地方的其他链索引问题)。

这应该工作:

quote_df.loc[:,'TVol'] = quote_df['TVol']/TVOL_SCALE

如何处理熊猫中的SettingWithCopyWarning

这篇文章是为读者谁,

  1. 想知道这个警告是什么意思
  2. 想了解抑制此警告的不同方法
  3. 希望了解如何改进他们的代码并遵循良好做法以避免将来出现此警告。

设置

np.random.seed(0)df = pd.DataFrame(np.random.choice(10, (3, 5)), columns=list('ABCDE'))dfA  B  C  D  E0  5  0  3  3  71  9  3  5  2  42  7  6  8  8  1

SettingWithCopyWarning是什么?

要知道如何处理这个警告,重要的是要了解它的含义以及为什么首先提出它。

过滤DataFrames时,可以对帧进行切片/索引,返回查看复制,具体取决于内部布局和各种实现细节。顾名思义,“视图”是原始数据的视图,因此修改视图可能会修改原始对象。另一方面,“副本”是原始数据的复制,修改副本对原始没有影响。

正如其他答案所提到的,创建SettingWithCopyWarning是为了标记“链式赋值”操作。考虑上面设置中的df。假设您想选择“B”列中的所有值,其中“A”列中的值>5。熊猫允许您以不同的方式执行此操作,有些比其他更正确。例如,

df[df.A > 5]['B']
1    32    6Name: B, dtype: int64

而且,

df.loc[df.A > 5, 'B']
1    32    6Name: B, dtype: int64

这些返回相同的结果,所以如果你只是读取这些值,那就没有区别了。那么,问题是什么?链式赋值的问题在于,通常很难预测返回的是视图还是副本,因此,当您尝试将值分配回时,这在很大程度上成为一个问题。在前面的例子的基础上,考虑解释器是如何执行这段代码的:

df.loc[df.A > 5, 'B'] = 4# becomesdf.__setitem__((df.A > 5, 'B'), 4)

通过对df. OTOH的单个__setitem__调用,考虑以下代码:

df[df.A > 5]['B'] = 4# becomesdf.__getitem__(df.A > 5).__setitem__('B', 4)

现在,根据__getitem__返回的是视图还是副本,__setitem__操作可能行不通

一般来说,您应该使用#0进行基于标签的赋值,使用#1进行基于整数/位置的赋值,因为规范保证它们始终对原始操作。此外,对于设置单个单元格,您应该使用#2#3

更多可以在留档中找到。

注释loc完成的所有布尔索引操作也可以用iloc完成。唯一的区别是iloc期望要么索引或布尔值的numpy数组的整数/位置,以及列的整数/位置索引。

例如,

df.loc[df.A > 5, 'B'] = 4

可以写为nas

df.iloc[(df.A > 5).values, 1] = 4

而且,

df.loc[1, 'A'] = 100

可以写成

df.iloc[1, 0] = 100

诸如此类。


只要告诉我如何抑制警告!

考虑对df的“A”列进行简单操作。选择“A”并除以2将引发警告,但该操作将起作用。

df2 = df[['A']]df2['A'] /= 2/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/IPython/__main__.py:1: SettingWithCopyWarning:A value is trying to be set on a copy of a slice from a DataFrame.Try using .loc[row_indexer,col_indexer] = value instead
df2A0  2.51  4.52  3.5

有几种方法可以直接消除这个警告:

  1. (推荐)使用#0对子集进行切片

     df2 = df.loc[:, ['A']]df2['A'] /= 2     # Does not raise
  2. 更改pd.options.mode.chained_assignment可以设置为None"warn""raise""warn"是默认值。None将完全抑制警告,"raise"将抛出SettingWithCopyError,阻止操作通过。

     pd.options.mode.chained_assignment = Nonedf2['A'] /= 2
  3. 做一个#0

     df2 = df[['A']].copy(deep=True)df2['A'] /= 2

@陈志立在评论中,提出了一种使用上下文管理器非侵入式更改模式(从这一要点修改)的好方法,仅在需要时设置模式,并在完成后将其重置回原始状态。

class ChainedAssignent:def __init__(self, chained=None):acceptable = [None, 'warn', 'raise']assert chained in acceptable, "chained must be in " + str(acceptable)self.swcw = chained
def __enter__(self):self.saved_swcw = pd.options.mode.chained_assignmentpd.options.mode.chained_assignment = self.swcwreturn self
def __exit__(self, *args):pd.options.mode.chained_assignment = self.saved_swcw

用法如下:

# Some code herewith ChainedAssignent():df2['A'] /= 2# More code follows

或者,提出例外

with ChainedAssignent(chained='raise'):df2['A'] /= 2
SettingWithCopyError:A value is trying to be set on a copy of a slice from a DataFrame.Try using .loc[row_indexer,col_indexer] = value instead

“XY问题”:我做错了什么?

很多时候,用户试图在不完全理解为什么首先提出这个异常的情况下寻找抑制这个异常的方法。这是XY问题的一个很好的例子,其中用户试图解决的问题“Y”实际上是更深层次问题“X”的症状。将根据遇到此警告的常见问题提出问题,然后呈现解决方案。

问题1我有一个DataFrame

dfA  B  C  D  E0  5  0  3  3  71  9  3  5  2  42  7  6  8  8  1

我想将“A”>5的值赋给1000。我的预期输出是

      A  B  C  D  E0     5  0  3  3  71  1000  3  5  2  42  1000  6  8  8  1

这样做的错误方法:

df.A[df.A > 5] = 1000         # works, because df.A returns a viewdf[df.A > 5]['A'] = 1000      # does not workdf.loc[df.A > 5]['A'] = 1000   # does not work

正确使用loc

df.loc[df.A > 5, 'A'] = 1000

问题21我正在尝试将单元格(1,'D')中的值设置为12345。我的预期输出是

   A  B  C      D  E0  5  0  3      3  71  9  3  5  12345  42  7  6  8      8  1

我尝试了不同的方式来访问这个单元格,例如df['D'][1].最好的方法是什么?

1。这个问题不是特别与警告有关,但是这是很好的了解如何做这个特定的操作正确以避免可能出现警告的情况未来。

您可以使用以下任何一种方法来执行此操作。

df.loc[1, 'D'] = 12345df.iloc[1, 3] = 12345df.at[1, 'D'] = 12345df.iat[1, 3] = 12345

问题3我试图子集值基于一些条件。我有一个数据帧

   A  B  C  D  E1  9  3  5  2  42  7  6  8  8  1

我想将“D”中的值赋值给123,使得“C”==5。我尝试过

df2.loc[df2.C == 5, 'D'] = 123

这似乎很好,但我仍然得到SettingWithCopyWarning!我该怎么解决这个问题?

这实际上可能是因为你的管道中更高的代码。你是从更大的东西创建df2的吗,比如

df2 = df[df.A > 5]

?在这种情况下,布尔索引将返回一个视图,因此df2将引用原始视图。您需要做的是将df2分配给复制

df2 = df[df.A > 5].copy()# Or,# df2 = df.loc[df.A > 5, :]

问题4我正在尝试从

中删除列“C”
   A  B  C  D  E1  9  3  5  2  42  7  6  8  8  1

但使用

df2.drop('C', axis=1, inplace=True)

抛出SettingWithCopyWarning。为什么会发生这种情况?

这是因为df2必须是作为其他切片操作的视图创建的,例如

df2 = df[df.A > 5]

这里的解决方案是要么做一个dfcopy(),要么像以前一样使用loc

后续初学者问题/备注

也许是对像我这样的其他初学者的澄清(我来自R,它的工作方式似乎有点不同)。以下看起来无害的功能代码不断产生设置与复制警告,我不知道为什么。我已经阅读并理解了“链式索引”的发布,但我的代码不包含任何:

def plot(pdb, df, title, **kw):df['target'] = (df['ogg'] + df['ugg']) / 2# ...

但是,后来,为时已晚,我看了一下在哪里调用plot()函数:

    df = data[data['anz_emw'] > 0]pixbuf = plot(pdb, df, title)

所以“df”不是一个数据帧,而是一个对象,它以某种方式记住它是通过索引数据帧创建的(那么这是一个视图吗?),这将使情节()中的行,

 df['target'] = ...

相当于

 data[data['anz_emw'] > 0]['target'] = ...

这是一个链式索引。

总之,

def plot(pdb, df, title, **kw):df.loc[:,'target'] = (df['ogg'] + df['ugg']) / 2

固定它。

在这里我直接回答问题,我们该如何处理呢?

切片后做一个.copy(deep=False)。见pandas.DataFrame.copy

等等,切片不返回副本吗?毕竟,这就是警告消息试图说的?阅读长答案:

import pandas as pddf = pd.DataFrame({'x':[1,2,3]})

这是一个警告:

df0 = df[df.x>2]df0['foo'] = 'bar'

这不是:

df1 = df[df.x>2].copy(deep=False)df1['foo'] = 'bar'

df0df1都是DataFrame对象,但它们的某些不同之处使熊猫能够打印警告。让我们来看看它是什么。

import inspectslice= df[df.x>2]slice_copy = df[df.x>2].copy(deep=False)inspect.getmembers(slice)inspect.getmembers(slice_copy)

使用您选择的diff工具,您将看到除了几个地址之外,唯一的实质性差异是:

|          | slice   | slice_copy || _is_copy | weakref | None       |

决定是否警告的方法是DataFrame._check_setitem_copy,它检查_is_copy。所以你开始了。做一个copy,这样你的DataFrame就不是_is_copy

警告建议使用.loc,但如果您在_is_copy的帧上使用.loc,您仍然会收到相同的警告。误导?是的。烦人?你打赌。有用吗?潜在地,当使用链式赋值时。但它不能正确检测链式赋值并不分青红皂白地打印警告。

有些人可能想简单地抑制警告:

class SupressSettingWithCopyWarning:def __enter__(self):pd.options.mode.chained_assignment = None
def __exit__(self, *args):pd.options.mode.chained_assignment = 'warn'
with SupressSettingWithCopyWarning():#code that produces warning

这个主题真的让熊猫感到困惑。幸运的是,它有一个相对简单的解决方案。

问题是数据过滤操作(例如loc)返回的是DataFrame的副本还是视图并不总是很清楚。因此,进一步使用这种过滤的DataFrame可能会令人困惑。

简单的解决方案是(除非你需要处理非常大的数据集):

每当您需要更新任何值时,请始终确保在分配之前显式复制DataFrame。

df  # Some DataFramedf = df.loc[:, 0:2]  # Some filtering (unsure whether a view or copy is returned)df = df.copy()  # Ensuring a copy is madedf[df["Name"] == "John"] = "Johny"  # Assignment can be done now (no warning)

由于这个问题已经在现有答案中得到了充分的解释和讨论,我将使用pandas.option_context(链接到留档示例)为上下文管理器提供一个简洁的熊猫方法——绝对不需要创建一个包含所有dunder方法和其他花里胡哨的自定义类。

首先是上下文管理器代码本身:

from contextlib import contextmanager
@contextmanagerdef SuppressPandasWarning():with pd.option_context("mode.chained_assignment", None):yield

再举一个例子:

import pandas as pdfrom string import ascii_letters
a = pd.DataFrame({"A": list(ascii_letters[0:4]), "B": range(0,4)})
mask = a["A"].isin(["c", "d"])# Even shallow copy below is enough to not raise the warning, but why is a mystery to me.b = a.loc[mask]  # .copy(deep=False)
# Raises the `SettingWithCopyWarning`b["B"] = b["B"] * 2
# Does not!with SuppressPandasWarning():b["B"] = b["B"] * 2

值得注意的是,这两种方法都不会修改a,这对我来说有点令人惊讶,即使是带有.copy(deep=False)的浅df副本也会阻止发出此警告(据我所知,浅副本至少也应该修改a,但它没有熊猫魔术。

当我从我使用.query()方法的预先存在的数据帧分配新的数据帧时,我在.apply()中遇到了这个问题。例如:

prop_df = df.query('column == "value"')prop_df['new_column'] = prop_df.apply(function, axis=1)

将返回此错误。在这种情况下,似乎可以解决错误的修复方法是将其更改为:

prop_df = df.copy(deep=True)prop_df = prop_df.query('column == "value"')prop_df['new_column'] = prop_df.apply(function, axis=1)

但是,这是没有效率,特别是在使用大型数据帧时,因为必须制作新副本。

如果您使用.apply()方法生成新列及其值,则可以通过添加.reset_index(drop=True)来解决错误并更有效地修复:

prop_df = df.query('column == "value"').reset_index(drop=True)prop_df['new_column'] = prop_df.apply(function, axis=1)

当我执行这部分代码时,我面临着同样的警告:

def scaler(self, numericals):scaler = MinMaxScaler()self.data.loc[:, numericals[0]] = scaler.fit_transform(self.data.loc[:, numericals[0]])self.data.loc[:, numericals[1]] = scaler.fit_transform(self.data.loc[:, numericals[1]])

其中scaler是一个MinMaxScaler,numericals[0]包含我的三个数字列的名称。

当我将代码更改为:

def scaler(self, numericals):scaler = MinMaxScaler()self.data.loc[:][numericals[0]] = scaler.fit_transform(self.data.loc[:][numericals[0]])self.data.loc[:][numericals[1]] = scaler.fit_transform(self.data.loc[:][numericals[1]])

所以,只是[:, ~]更改为[:][~]

只需在警告出现之前使用.copy()方法创建数据框的副本,即可删除所有警告。

发生这种情况是因为我们不想对原始quote_df进行更改。换句话说,我们不想玩我们为quote_df创建的quote_df对象的引用。

quote_df = quote_df.copy()

为我工作:

import pandas as pd# ...pd.set_option('mode.chained_assignment', None)

这可能仅适用于NumPy,这意味着您可能需要导入它,但我在示例NumPy中使用的数据对于计算来说并不重要,但您可以通过使用下面的这一行代码来简单地停止此setting With Copy警告消息:

np.warnings.filterwarnings('ignore')

在我的例子中,我会根据索引创建一个新列,但我得到了和你一样的警告:

df_temp["Quarter"] = df_temp.index.quarter

我使用插入()而不是直接赋值,它对我有用:

df_temp.insert(loc=0, column='Quarter', value=df_temp.index.quarter)