如何处理Pandas中的SettingWithCopyWarning警告

1381

背景

我刚刚将我的Pandas从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 instead
  quote_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_SCALE
    quote_df['TAmt']   = quote_df['TAmt']/TAMT_SCALE
    quote_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 instead
  quote_df['TVol']   = quote_df['TVol']/TVOL_SCALE
E:\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 instead
  quote_df['TAmt']   = quote_df['TAmt']/TAMT_SCALE
E:\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 instead
  quote_df['TDate']  = quote_df.TDate.map(lambda x: x[0:4]+x[5:7]+x[8:10])

4
这是一个上下文管理器,用于暂时设置警告级别。https://gist.github.com/notbanker/2be3ed34539c86e22ffdd88fd95ad8bc - Peter Cotton
1
官方文档详细解释了http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy。 - wyx
6
df.set_value已被弃用,Pandas现在建议使用.at[].iat[]。文档在这里:https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.at.html - Kyle C
10
使用 df.loc[:, foo] 可以避免 SettingWithCopyWarning 警告,而 df[foo] 会引起 SettingWithCopyWarning 警告。 - Asclepius
这个回答解决了你的问题吗?使用索引为pandas DataFrame中的特定单元格设置值 - Serge Stroobandt
24个回答

1622

SettingWithCopyWarning 是为了标记可能会引起混淆的“链式”赋值,比如以下示例,特别是当第一个选择返回一个副本时,这种方法并不总是按预期工作。 [有关详细讨论,请参见GH5390GH5597。]

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 pd
pd.options.mode.chained_assignment = None  # default='warn'

其他资源


59
我使用了数据框的一个切片,在该切片上进行修改时出现了错误。我通过对原始数据框执行.copy()创建了这个切片,并且这样做可以解决问题。 - Rishabh Agrahari
我应该如何处理 df = df[df['A'].notnull()] - Mehdi Abbassi
10
@Garrett,请考虑将@RishabhAgrahari的评论添加到您的答案中。通过在切片上调用.copy()来告诉pandas您想要操作副本,这是一个更好的想法,而不是在运行时完全禁用所有情况的警告。 - Zoltán
1
在我的情况下,警告并没有设置在要修改的那一行。我在第一行筛选了数据,然后在第二行创建了一个计算字段。警告显示在第二行,实际上解决方案是通过在第一行添加调用.copy()来修改第一行。 这是具有误导性的,有时这两行代码之间相隔很长的距离。 - frank
2
在切片上使用.copy()是一个不好的解决方法,因为它会引入额外的、不必要的副本。像df[df.a > 2]这样的子集操作已经创建了一个新的数据框,所以没有算法上需要进行额外的复制。 - Cameron Bieganek
总结一下:如果你只是想消除警告,可以使用 pd.options.mode.chained_assignment = None。这不是长期的解决办法,但可以应付眼前的问题。 - John Peurifoy

831
如何在 Pandas 中处理 SettingWithCopyWarningChainedAssignmentError 问题?
本文旨在帮助读者:
  1. 理解此警告的含义
  2. 了解不同方法来消除此警告
  3. 学习如何改进代码,遵循良好实践以避免在未来出现此警告。
设置
np.random.seed(0)
df = pd.DataFrame(np.random.choice(10, (3, 5)), columns=list('ABCDE'))
df
   A  B  C  D  E
0  5  0  3  3  7
1  9  3  5  2  4
2  7  6  8  8  1

什么是SettingWithCopyWarning

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

在过滤数据框时,可能会对框架进行切片/索引,以返回一个视图副本,具体取决于内部布局和各种实现细节。 "视图"就像其名称所示,是原始数据的视图,因此修改视图可能会修改原始对象。另一方面,"副本"是从原始数据复制的数据,修改副本不会影响原始数据。

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

df[df.A > 5]['B']

1    3
2    6
Name: B, dtype: int64

而且,

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

1    3
2    6
Name: B, dtype: int64

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

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

通过单个__setitem__调用到df。另一方面,考虑以下代码:

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

现在,取决于__getitem__返回的是视图还是副本,__setitem__操作可能无法正常工作

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

更多信息请参见文档

Note All boolean indexing operations done with loc can also be done with iloc. The only difference is that iloc expects either integers/positions for index or a numpy array of boolean values, and integer/position indexes for the columns.

For example,

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

Can be written nas

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

And,

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

Can be written as

df.iloc[1, 0] = 100

And so on.

从pandas >= 2.0开始,你可以启用写时复制优化来节省内存并避免在可能的情况下进行数据复制,直到写入。

可以通过以下方式启用:

pd.options.mode.copy_on_write = True

在此之后,尝试进行链式赋值将会导致

ChainedAssignmentError: A value is trying to be set on a copy of a DataFrame or Series through chained assignment.
When using the Copy-on-Write mode, such chained assignment never works to update the original DataFrame or Series, because the intermediate object on which we are setting values always behaves as a copy.

Try using '.loc[row_indexer, col_indexer] = value' instead, to perform the assignment in a single step.

这个错误和SettingWithCopyWarning类似,在相似的环境中被触发。


告诉我如何抑制警告!

考虑对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

df2
     A
0  2.5
1  4.5
2  3.5

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

  1. (推荐) 使用 loc 切片子集:

     df2 = df.loc[:, ['A']]
     df2['A'] /= 2     # 不会引发警告
    
  2. 更改 pd.options.mode.chained_assignment 可以设置为 None"warn""raise"。默认为 "warn"None 将完全抑制警告,"raise" 将抛出 SettingWithCopyError,防止操作继续进行。

     pd.options.mode.chained_assignment = None
     df2['A'] /= 2
    
  3. 创建一个 deepcopy

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

@Peter Cotton 在评论中提出了一种非侵入式地改变模式的好方法(修改自this gist),使用上下文管理器,仅在需要时设置模式,并在完成后将其重置回原始状态。

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_assignment
        pd.options.mode.chained_assignment = self.swcw
        return self

    def __exit__(self, *args):
        pd.options.mode.chained_assignment = self.saved_swcw

使用方法如下:

# Some code here
with 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 问题的很好的例子,其中用户试图解决一个实际上是更深层次根源问题 "X" 的症状问题 "Y"。将根据遇到此警告的常见问题提出问题,并随后提供解决方案。

Question 1 I have a DataFrame

df
       A  B  C  D  E
    0  5  0  3  3  7
    1  9  3  5  2  4
    2  7  6  8  8  1

I want to assign values in col "A" > 5 to 1000. My expected output is

      A  B  C  D  E
0     5  0  3  3  7
1  1000  3  5  2  4
2  1000  6  8  8  1

错误的做法:

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

使用loc的正确方式:

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

Question 21 I am trying to set the value in cell (1, 'D') to 12345. My expected output is

   A  B  C      D  E
0  5  0  3      3  7
1  9  3  5  12345  4
2  7  6  8      8  1

I have tried different ways of accessing this cell, such as df['D'][1]. What is the best way to do this?

1. This question isn't specifically related to the warning, but it is good to understand how to do this particular operation correctly so as to avoid situations where the warning could potentially arise in future.

您可以使用以下任何一种方法来实现此目的。
df.loc[1, 'D'] = 12345
df.iloc[1, 3] = 12345
df.at[1, 'D'] = 12345
df.iat[1, 3] = 12345

Question 3 I am trying to subset values based on some condition. I have a DataFrame

   A  B  C  D  E
1  9  3  5  2  4
2  7  6  8  8  1

I would like to assign values in "D" to 123 such that "C" == 5. I tried

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

Which seems fine but I am still getting the SettingWithCopyWarning! How do I fix this?

这可能是因为你的管道中更高层的代码问题。你是不是从一个更大的东西(比如)创建了df2
df2 = df[df.A > 5]

在这种情况下,布尔索引将返回一个视图,因此df2将引用原始数据。你需要做的是将df2分配给一个副本
df2 = df[df.A > 5].copy()
# Or,
# df2 = df.loc[df.A > 5, :]

Question 4 I'm trying to drop column "C" in-place from

   A  B  C  D  E
1  9  3  5  2  4
2  7  6  8  8  1

But using

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

Throws SettingWithCopyWarning. Why is this happening?

这是因为df2必须已经被创建为某些其他切片操作的视图,比如:
df2 = df[df.A > 5]

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


31
请告诉我,如果您的情况不在第三部分问题列表中,我将修改我的帖子。 - cs95
4
@cs95:你能否在以下情况下添加一个XY说明,即当你试图基于现有列进行简单数学运算来创建一个新列时。例如 df ['new_col'] = df ['old_col'] / 2,其中'new_col'还不存在。谢谢 - Bryan P
1
@cs95 - 谢谢。几乎每个人都关注你的问题1和2。但是,我在第3个问题中恰好遇到了子集问题。我发现在子网创建后,_is_copy不再是None,这导致我使用.copy()。 - Mark
3
非常感谢!我在我的代码中经常使用.loc,因为我意识到了“链式赋值”问题,但是偶尔仍然会遇到讨厌的SettingWithCopyWarning。结果发现我的问题就是你在“问题3”中提到的。这花费了我数月的时间才意识到,因此也许应该在文档中更清楚地指出...再次非常感谢! - Pythonist
1
@cs95 针对 df["widget"].replace("foo", "bar", inplace=True) 你怎么看? - henning
显示剩余9条评论

176

通常,SettingWithCopyWarning 的目的是向用户(尤其是新用户)显示他们可能在副本上操作而不是原始数据。存在一些误报警情况(如果您知道自己在做什么,则可能是可以的)。一种可能的解决方案是像 @Garrett 建议的那样简单地关闭默认情况下的警告。

以下是另一种选择:

In [1]: df = DataFrame(np.random.randn(5, 2), columns=list('AB'))

In [2]: dfa = df.ix[:, [1, 0]]

In [3]: dfa.is_copy
Out[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

楼上提供的代码虽然是合法的,可能也是我自己使用的方式,但技术上却是一个需要警告的情况,而不是误报。另一种避免此警告的方法是通过reindex进行选择操作,例如:

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

11
我认为说存在假阳性是轻描淡写了。我从来没有因为这个警告而受到帮助,反倒是它经常干扰我的输出。这也是一种糟糕的编程实践:如果你因为知道这些警告只是无用信息,开始忽略输出中的警告,你可能会错过真正的问题。而且总是不得不关闭相同的警告也很烦人。 - Marses

58

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

在切片后使用.copy(deep=False)。请参阅pandas.DataFrame.copy

等等,难道切片不会返回一个副本吗?毕竟,这就是警告消息试图说明的内容吗?详见长答案:

import pandas as pd
df = 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'

无论是df0还是df1,都是DataFrame对象,但它们之间有一些不同之处,使得pandas会打印出警告。我们来找出是什么造成了这种情况。

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

使用您所选择的差异工具,您会发现除了一些地址以外,唯一的实质性区别就是这个:

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

决定是否发出警告的方法是DataFrame._check_setitem_copy,它检查_is_copy。所以请创建一个copy,这样您的DataFrame就不会被标记为_is_copy

警告建议使用.loc,但如果您在一个被标记为_is_copy的框架上使用.loc,仍然会收到相同的警告。误导?是的。烦人?当然。有帮助吗?潜在地,在链接赋值时。但它无法正确检测链式赋值,并会 indiscriminately 打印警告信息。


2
不错的侦探工作。FWIW,我还发现对于原始df,_is_copyNone,而对于切片,则为弱引用。此外,对于切片上的_is_copy()方法返回原始df的所有行。但是由_is_copy打印的引用与原始df的id不同。切片是否会创建一个副本?另外,我想知道浅复制是否会在以后或新版本的pandas中导致其他问题? - user650654
4
这个回答的写作风格无疑值得获得单独的奖章。 - mirekphd
1
毫无疑问,这是对问题最具体和直接的回答。非常好地表达了出来。 - waykiki

49

关于Pandas数据框副本的警告

当您执行以下操作时:

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

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

您在此数据框中所做的任何更改都不会影响原始数据框。

这就是pandas试图警告您的内容。


为什么使用.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代替

pandas开发人员认识到.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对象来执行神奇操作。


34

这个话题在Pandas中真的很令人困惑。幸运的是,它有一个相对简单的解决方案。

问题在于,数据过滤操作(例如loc)是否返回DataFrame的副本或视图并不总是清晰明确。因此,进一步使用这样过滤的DataFrame可能会令人困惑。

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

每当您需要更新任何值时,请务必在赋值之前显式复制DataFrame。

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

对于大数据集,你可以制作一个浅表(deep=False)的复制品。但似乎压制警告太多了。 - memeplex

24

只需要简单地:

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

19

在使用.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)

13

为了消除任何疑虑,我的解决方案是制作切片的深拷贝而不是常规拷贝。这可能并不适用于您的上下文(内存限制/切片大小,性能降低的潜在可能性-特别是如果像我一样在循环中进行复制等...)

明确一点,在此处我收到了以下警告:

/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 DataFrame
See 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    B
0    111    121
1    112    122
2    113    123


>> df2 = df1
>> df2

A    B
0    111    121
1    112    122
2    113    123

# Dropping a column on df1 affects df2
>> df1.drop('A', axis=1, inplace=True)
>> df2
    B
0    121
1    122
2    123

有可能避免对df1所做的更改影响到df2。注意:你可以通过使用df.copy()来避免导入copy.deepcopy

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

A    B
0    111    121
1    112    122
2    113    123

>> import copy
>> df2 = copy.deepcopy(df1)
>> df2
A    B
0    111    121
1    112    122
2    113    123

# Dropping a column on df1 does not affect df2
>> df1.drop('A', axis=1, inplace=True)
>> df2
    A    B
0    111    121
1    112    122
2    113    123

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

这实际上说明了警告的含义。

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

    A    B
0    111    121
1    112    122
2    113    123

>> df2 = df1
>> df2

    A    B
0    111    121
1    112    122
2    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

B
0    121
1    122
2    123

可以避免对df2的更改影响到df1。

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

    A    B
0    111    121
1    112    122
2    113    123

>> import copy
>> df2 = copy.deepcopy(df1)
>> df2

A    B
0    111    121
1    112    122
2    113    123

>> df2.drop('A', axis=1, inplace=True)
>> df1

A    B
0    111    121
1    112    122
2    113    123

10

这应该可以运行:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接