社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
私信  •  关注

cs95 firelynx

cs95 firelynx 最近创建的主题
cs95 firelynx 最近回复了
6 年前
回复了 cs95 firelynx 创建的主题 » 用Python固定复制警告(复制)

熊猫数据帧复制警告

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

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 相反

熊猫开发商认识到 对象很臭[推测性地],因此创建了两个新对象,有助于数据的添加和分配。(另一个是 .iloc )

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

.loc位置 意在修改现有的DATAFAFRAMILE,这是更高效的内存。

.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

这将只读取您感兴趣的列,并正确命名它们。不用用邪恶 反对做神奇的事情。

6 年前
回复了 cs95 firelynx 创建的主题 » 用Python固定复制警告(复制)

如何处理 SettingWithCopyWarning

这篇文章是为读者准备的,

  1. 想了解压制这种警告的不同方法
  2. 希望了解如何改进他们的代码,并遵循良好的实践,以避免在将来出现这种警告。

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

什么是 ?

要知道如何处理这一警告,首先必须了解它的含义和提出原因。

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

如其他答案所述 设置复制警告 df 在上面的设置中。假设要选择“B”列中的所有值,其中“A”列中的值为5。熊猫允许你用不同的方式来做这件事,有些比其他更正确。例如,

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.A > 5]['B'] = 4
# becomes
df.__getitem__(df.A > 5).__setitem__('B", 4)

__getitem__ 返回视图或副本 操作 可能不起作用

一般来说,你应该使用 loc iloc 对于基于整数/位置的赋值,因为规范保证它们始终在原始值上操作。另外,对于设置单个单元格,应使用 at iat .

更多可以在 documentation

注意
所有布尔索引操作完成 位置 也可以用 . 唯一的区别是 iloc公司 索引或布尔值numpy数组的整数/位置,以及

例如,

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

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

而且,

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

可以写成

df.iloc[1, 0] = 100

等等。


考虑对 数据框 . 选择“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. 做一个 deepcopy

    df2 = df[['A']].copy(deep=True)
    df2['A'] /= 2
    
  2. 改变 pd.options.mode.chained_assignment
    可以设置为 None , "warn" "raise" “警告” 是默认值。 将完全抑制警告,并且 “提高” 会抛出一个 SettingWithCopyError

    pd.options.mode.chained_assignment = None
    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 problem ,其中用户试图解决问题“Y”,这实际上是根深蒂固的问题“X”的症状。将根据遇到此警告的常见问题提出问题,然后提出解决方案。

问题1

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

我想将“A”列中的值指定为5到1000。我的预期产出是

      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

位置 :

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


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

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

我试过不同的方法进入这个牢房,比如 df['D'][1]

一。这个问题与警告没有特别的关系,但是 很好地理解了如何正确地执行这个特殊的操作 未来。

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


问题3
我试图根据某些条件对值进行子集。我有一个 数据帧

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

我想把“D”中的值赋给123,这样“C”==5。我

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

看起来不错,但我是 仍然 得到 设置复制警告 ! 我该怎么解决?

df2 从更大的地方,比如

df2 = df[df.A > 5]

? 在这种情况下,布尔索引将返回一个视图,因此 df2型 df2型 给一个 :

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



我想把C列从

A B C D E
1 9 3 5 2 4

但是使用

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

投掷 设置复制警告 . 为什么会这样?

df2型 必须是从其他切片操作创建的视图,例如

df2=df[df.A>5]

copy() 属于 数据框 ,或使用