我有一个数据框说 release_dates
发布日期
我使用一些条件进行过滤并将其命名为b
b = release_dates[(release_dates.title.str.startswith('The Hobbit')) &
(release_dates.country =='USA')]
现在我想要通过从日期列中提取来显示月份的其他列。 我使用了下面的命令,它工作正常但抛出了一个错误
b['month'] = b['date'].dt.month #code1
C:\Users\user110244\Anaconda3\lib\site-packages\pandas\core\indexing.py:288: 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
我读了documentation根据代码的建议和我的理解,我开始知道我应该使用 below 命令(在链索引的情况下),因为使用 above 命令 非常困难预测它是返回一个 View 还是一个副本(这取决于数组的内存布局,pandas 对此不作任何保证)并且根据文档,code2 比 code1 更有效。
b.loc[:,'month']=b.loc[:,'date'].dt.month #code2
但是使用它也会抛出同样的错误。
有人可以解释为什么会这样吗?我如何确保我的代码在“a”和“b”两种情况下都是正确的? 如何关闭此警告?
我还想指出一件事,即我在不同条件下使用了相同的代码,但没有出现任何错误
a =release_dates[(release_dates.title.str.contains('Christmas'))&
(release_dates.country =='USA')].sort_values('year')
a['month'] = a['date'].dt.month
a.head()
最佳答案
正如 Edchum 在他的评论中清楚地解释的那样,您在第一段代码中使用了 .sort() 让 python 知道用户知道,它是一个副本而不是一个 View 。
每当我们执行切片或过滤时,我们都会得到一个 View 或一个副本。但是,Pandas 文档没有指定任何关于您应该期望 View 或副本的规则。
让我试着扩展一下。 避免此类警告的一种简单方法是使用 .copy()
b = (release_dates.title.str.startswith('The Hobbit')) &
(release_dates.country =='USA')
b1 = b.copy()
b1['month'] = b1['date'].dt.month #code1
通过这样做,您明确地告诉 Python 您正在处理什么,即在 View 上或在副本上,Python 将不会显示警告。
但请记住,每次复制都会消耗大量内存。所以只要有必要就去做。
您还可以使用
检查两个对象是否指向同一内存np.may_share_memory(b,b1)
False
为特定对象关闭警告的另一种方法是使用 .is_copy()=False 在这种情况下,我们可以使用
b.is_copy()= False
关于python - Pandas 中的 SettingWithCopyWarning 异常行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39074931/