说我有一个数据帧
import pandas as pd
import numpy as np
foo = pd.DataFrame(np.random.random((10,5)))
Run Code Online (Sandbox Code Playgroud)
我从我的数据子集创建另一个数据帧:
bar = foo.iloc[3:5,1:4]
Run Code Online (Sandbox Code Playgroud)
确实bar持有这些元素的副本foo?有没有办法创建view这些数据呢?如果是这样,如果我尝试修改此视图中的数据会发生什么?Pandas是否提供任何类型的写时复制机制?
Python 3.4和Pandas 0.15.0
df是一个数据帧,col1是一列.使用下面的代码,我正在检查值10的存在并用1000替换这些值.
df.col1[df.col1 == 10] = 1000
Run Code Online (Sandbox Code Playgroud)
这是另一个例子.这一次,我正在根据索引更改col2中的值.
df.col2[df.index == 151] = 500
Run Code Online (Sandbox Code Playgroud)
这两个都产生以下警告:
-c:1: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
See the the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
Run Code Online (Sandbox Code Playgroud)
最后,
cols = ['col1', 'col2', 'col3']
df[cols] = df[cols].applymap(some_function)
Run Code Online (Sandbox Code Playgroud)
这会产生类似的警告,并附加一条建议:
Try using .loc[row_indexer,col_indexer] = value instead
Run Code Online (Sandbox Code Playgroud)
我不确定我理解警告中指出的讨论.编写这三行代码的更好方法是什么?
请注意,操作有效.
我有一大块代码,在某些地方,在pandas中产生一个带有复制警告的设置(这个问题).
我知道如何解决问题,但我找不到它的行号!有没有办法退出行号(除了蛮力方法,如调试步进或多次打印)?我得到的唯一输出是下面的,它没有上升到我的代码堆栈:
C:\Anaconda3\lib\site-packages\pandas\core\frame.py:2302: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame **kwargs)
Run Code Online (Sandbox Code Playgroud) 我想用Pandas DataFrame大于任意数字(在这种情况下NaN为100)的值替换(因为这个值很大,表示实验失败).以前我用它来替换不需要的值:
sve2_all[sve2_all[' Hgtot ng/l'] > 100] = np.nan
Run Code Online (Sandbox Code Playgroud)
但是,我收到以下错误:
-c:3: 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
C:\Users\AppData\Local\Enthought\Canopy32\User\lib\site-packages\pandas\core\indexing.py:346: 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
self.obj[item] = s
Run Code Online (Sandbox Code Playgroud)
从这个StackExchange问题来看,似乎有时候这个警告可以被忽略,但我不能很好地跟进讨论,以确定这是否适用于我的情况.这个警告基本上让我知道我会覆盖我的一些价值观DataFrame吗?
编辑:据我所知,一切都表现得如此.跟进是我取代非标准价值的方法吗?有没有更好的方法来取代价值观?
起初,我尝试编写一些看起来像这样的代码:
import numpy as np
import pandas as pd
np.random.seed(2016)
train = pd.DataFrame(np.random.choice([np.nan, 1, 2], size=(10, 3)),
columns=['Age', 'SibSp', 'Parch'])
complete = train.dropna()
complete['AgeGt15'] = complete['Age'] > 15
Run Code Online (Sandbox Code Playgroud)
获得SettingWithCopyWarning后,我尝试使用.loc:
complete.loc[:, 'AgeGt15'] = complete['Age'] > 15
complete.loc[:, 'WithFamily'] = complete['SibSp'] + complete['Parch'] > 0
Run Code Online (Sandbox Code Playgroud)
但是,我仍然得到同样的警告.是什么赋予了?
我已经查看了一堆与此问题相关的问题和答案,但我仍然发现我在我不期望的地方得到了这个切片警告的副本.此外,它在我之前运行良好的代码中出现,让我想知道某种更新是否可能是罪魁祸首.
例如,这是一组代码,我所做的就是将Excel文件读入一个pandas DataFrame,并减少df[[]]语法中包含的列集.
izmir = pd.read_excel(filepath)
izmir_lim = izmir[['Gender','Age','MC_OLD_M>=60','MC_OLD_F>=60','MC_OLD_M>18','MC_OLD_F>18','MC_OLD_18>M>5','MC_OLD_18>F>5',
'MC_OLD_M_Child<5','MC_OLD_F_Child<5','MC_OLD_M>0<=1','MC_OLD_F>0<=1','Date to Delivery','Date to insert','Date of Entery']]
Run Code Online (Sandbox Code Playgroud)
现在,我对此izmir_lim文件所做的任何进一步更改都会引发切片警告的副本.
izmir_lim['Age'] = izmir_lim.Age.fillna(0)
izmir_lim['Age'] = izmir_lim.Age.astype(int)
Run Code Online (Sandbox Code Playgroud)
/Users/samlilienfeld/anaconda/lib/python3.5/site-packages/ipykernel/ main .py:2:SettingWithCopyWarning:尝试在DataFrame的切片副本上设置值.尝试使用.loc [row_indexer,col_indexer] = value
我很困惑因为我认为df[[]]列子集默认返回了一个副本.我发现抑制错误的唯一方法是明确添加df[[]].copy().我本来可以发誓,过去我没有那么做,也没有提出切片错误的副本.
同样,我有一些其他代码在数据帧上运行一个函数,以某种方式过滤它:
def lim(df):
if (geography == "All"):
df_geo = df
else:
df_geo = df[df.center_JO == geography]
df_date = df_geo[(df_geo.date_survey >= start_date) & (df_geo.date_survey <= end_date)]
return df_date
df_lim = lim(df)
Run Code Online (Sandbox Code Playgroud)
从这一点开始,我对任何值进行的任何更改都会df_lim引发切片错误的副本.我找到的唯一方法是将函数调用更改为:
df_lim = lim(df).copy()
Run Code Online (Sandbox Code Playgroud)
这对我来说似乎不对.我错过了什么?看起来这些用例应该默认返回副本,我可以发誓上次运行这些脚本时我没有遇到这些错误.
我只需要开始添加.copy()到处吗?似乎应该有一个更清洁的方法来做到这一点.任何见解或帮助都非常感谢.
我一直在阅读这个链接的"返回视图与副本".我真的不明白的是如何链接分配在熊猫的概念工作和如何的使用.ix(),.iloc()或者.loc()影响它.
我得到SettingWithCopyWarning以下代码行的警告,其中data是Panda数据帧,并且amount是该数据帧中的列(系列)名称:
data['amount'] = data['amount'].astype(float)
data["amount"].fillna(data.groupby("num")["amount"].transform("mean"), inplace=True)
data["amount"].fillna(mean_avg, inplace=True)
Run Code Online (Sandbox Code Playgroud)
看看这段代码,我做的事情显然不是很理想吗?如果是这样,你能告诉我更换代码行吗?
我知道下面的警告,并且认为我的案例中的警告是误报:
链式分配警告/异常旨在通知用户可能无效的分配.可能存在误报; 无意中报告链式作业的情况.
编辑:导致第一次复制警告错误的代码.
data['amount'] = data.apply(lambda row: function1(row,date,qty), axis=1)
data['amount'] = data['amount'].astype(float)
def function1(row,date,qty):
try:
if(row['currency'] == 'A'):
result = row[qty]
else:
rate = lookup[lookup['Date']==row[date]][row['currency'] ]
result = float(rate) * float(row[qty])
return result
except ValueError: # generic exception clause
print "The current row causes an exception:"
Run Code Online (Sandbox Code Playgroud) 它是众所周知的(和理解)分配到切片时,大熊猫的行为本质上是不可预测的.但我常常被警告SettingWithCopy警告.
为什么警告不是在以下两个代码片段中生成的,哪些技术可以减少无意中编写此类代码的可能性?
# pandas 0.18.1, python 3.5.1
import pandas as pd
data = pd.DataFrame({'a': [1, 2, 3], 'b': ['a', 'b', 'c']})
new_data = data[['a', 'b']]
data = data['a']
new_data.loc[0, 'a'] = 100 # no warning, doesn't propagate to data
data[0] == 1
True
data = pd.DataFrame({'a': [1, 2, 3], 'b': ['a', 'b', 'c']})
new_data = data['a']
data = data['a']
new_data.loc[0] = 100 # no warning, propagates to data
data[0] == 100
True
Run Code Online (Sandbox Code Playgroud)
我认为解释是,当父数据帧仍可从当前上下文访问时,pandas仅生成警告.(这将是检测算法的一个弱点,正如我之前的例子所示.)
在下一个片段中,AFAIK原始的双列DataFrame不再可访问,但pandas警告机制设法触发(幸运的是): …
我的代码的以下行导致警告:
import pandas as pd
s = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=list('ABCD'))
s.loc[-1] = [5,np.nan,np.nan,6]
grouped = s.groupby(['A'])
for key_m, group_m in grouped:
group_m.loc[-1] = [10,np.nan,np.nan,10]
C:\Anaconda3\lib\site-packages\ipykernel\__main__.py:10: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
Run Code Online (Sandbox Code Playgroud)
根据文档,这是推荐的做法,所以发生了什么?
谢谢你的帮助.
我猜这两个问题是相关的,因此我将它们一起发布:
1.-是否可以在链接的分配中放置类型提示?
这两次尝试均失败:
>>> def foo(a:int):
... b: int = c:int = a
File "<stdin>", line 2
b: int = c:int = a
^
SyntaxError: invalid syntax
>>> def foo(a:int):
... b = c:int = a
File "<stdin>", line 2
b = c:int = a
^
SyntaxError: invalid syntax
Run Code Online (Sandbox Code Playgroud)
2.-是否可以在多个分配中放入类型提示?
这些是我的尝试:
>>> from typing import Tuple
>>> def bar(a: Tuple[int]):
... b: int, c:int = a
File "<stdin>", line 2
b: int, c:int = a
^
SyntaxError: invalid syntax
>>> …Run Code Online (Sandbox Code Playgroud) 我尝试delete一些列并在列中转换一些值
df2.drop(df2.columns[[0, 1, 3]], axis=1, inplace=True)
df2['date'] = df2['date'].map(lambda x: str(x)[1:])
df2['date'] = df2['date'].str.replace(':', ' ', 1)
df2['date'] = pd.to_datetime(df2['date'])
Run Code Online (Sandbox Code Playgroud)
我得到的所有这些字符串
df2.drop(df2.columns[[0, 1, 3]], axis=1, inplace=True)
C:/Users/????? ???????????/Desktop/projects/youtube_log/filter.py:11: 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
Run Code Online (Sandbox Code Playgroud)
那有什么问题?
我一直在四处阅读熊猫文档here并尝试从here和here周围发布的问题中尝试不同的代码行,我似乎无法摆脱带有复制警告的设置。我更愿意学习以“正确”的方式对其进行编码,而不是仅仅忽略警告。
以下代码行在 for 循环中,我不想多次生成此警告,因为它可能会减慢速度。
我正在尝试创建一个名称为:'E'+vs 的新列,其中 vs 是 for 循环中列表中的一个字符串
但是对于他们中的每一个,我仍然收到以下警告,即使是最后 3 行:
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
Run Code Online (Sandbox Code Playgroud)
以下是我迄今为止尝试过的麻烦行:
#based on research, the first two seem to be the "wrong" way
df_out['E'+vs] = df_out[kvs].rolling(v).mean().copy()
df_out['E'+vs] = df_out[kvs].rolling(v).mean()
df_out.loc[:,'E'+vs] = df_out[kvs].rolling(v).mean().copy()
df_out.loc[:,'E'+vs] = df_out[kvs].rolling(v).mean()
df_out.loc[:,'E'+vs] = df_out.loc[:,kvs].rolling(v).mean()
Run Code Online (Sandbox Code Playgroud)
另一个给出 SettingWithCopyWarning 的是这样的:
df_out.dropna(inplace=True,axis=0)
Run Code Online (Sandbox Code Playgroud)
这个也发出了警告(但我认为这个会)
df_out = df_out.dropna(inplace=True,axis=0)
Run Code Online (Sandbox Code Playgroud)
如何正确执行这两个操作? …
python ×12
pandas ×11
python-3.x ×2
warnings ×2
copy ×1
dataframe ×1
python-2.7 ×1
type-hinting ×1