Pandas:了解操作何时影响原始数据帧

2024-05-03

我喜欢 pandas 并且已经使用它很多年了,并且非常有信心我能够很好地掌握如何对数据帧进行子集化并适当地处理视图与副本(尽管我使用了很多断言来确保)。我还知道有很多关于SettingWithCopyWarning的问题,例如如何处理Pandas中的SettingWithCopyWarning? https://stackoverflow.com/questions/20625582/how-to-deal-with-settingwithcopywarning-in-pandas以及最近一些很棒的指南,帮助您在发生这种情况时保持头脑清醒,例如理解pandas中的SettingWithCopyWarning https://www.dataquest.io/blog/settingwithcopywarning/.

但我也知道具体的事情,比如引用这个答案 https://stackoverflow.com/a/17961468/8022335不再出现在最新的文档中(0.22.0)并且多年来许多事情已被弃用(导致一些不合适的旧答案),并且事情是持续改变 https://stackoverflow.com/a/34908742/8022335.

最近,在教 pandas 使新手具备非常基本的 Python 通用知识之后,例如避免链式索引(以及使用.iloc/.loc),我仍然努力提供一般经验法则知道什么时候需要注意SettingWithCopyWarning(例如,当可以安全地忽略它时)。

我个人发现,根据某些规则(例如切片或布尔运算)对数据帧进行子集化的特定模式,然后修改该子集,独立于原始数据框,是比文档建议的更常见的操作。在这种情况下我们想要修改副本而不是原始文件而且这个警告让新手感到困惑/害怕。

我知道提前知道何时返回视图与副本并不简单,例如
Pandas 使用什么规则来生成视图和副本? https://stackoverflow.com/questions/23296282/what-rules-does-pandas-use-to-generate-a-view-vs-a-copy
检查数据框是在 Pandas 中复制还是查看 https://stackoverflow.com/questions/26879073/checking-whether-data-frame-is-copy-or-view-in-pandas

因此,我正在寻找一个更一般(初学者友好)问题的答案:什么时候对子集数据帧执行操作会影响创建它的原始数据帧,它们什么时候是独立的?.

我在下面创建了一些我认为似乎合理的案例,但我不确定是否缺少我所缺少的“陷阱”,或者是否有任何更简单的方法来思考/检查这一点。我希望有人能够确认我对以下用例的直觉是正确的,因为与我上面的问题有关。

import pandas as pd
df1 = pd.DataFrame({'A':[2,4,6,8,10],'B':[1,3,5,7,9],'C':[10,20,30,40,50]})

1) 警告:否
原改:无

# df1 will be unaffected because we use .copy() method explicitly 
df2 = df1.copy()
#
# Reference: docs
df2.iloc[0,1] = 100

2)警告:是的(我不太明白为什么)
原改:无

# df1 will be unaffected because .query() always returns a copy
#
# Reference:
# https://stackoverflow.com/a/23296545/8022335
df2 = df1.query('A < 10')
df2.iloc[0,1] = 100

3) 警告:是
原改:无

# df1 will be unaffected because boolean indexing with .loc
# always returns a copy
#
# Reference:
# https://stackoverflow.com/a/17961468/8022335
df2 = df1.loc[df1['A'] < 10,:]
df2.iloc[0,1] = 100

4) 警告:否
原改:无

# df1 will be unaffected because list indexing with .loc (or .iloc)
# always returns a copy
#
# Reference:
# Same as 4)
df2 = df1.loc[[0,3,4],:]
df2.iloc[0,1] = 100

5) 警告:否
原始更改:是(对新手来说很困惑,但很有意义)

# df1 will be affected because scalar/slice indexing with .iloc/.loc
# always references the original dataframe, but may sometimes 
# provide a view and sometimes provide a copy
#
# Reference: docs
df2 = df1.loc[:10,:]
df2.iloc[0,1] = 100

tl;dr当从原始数据帧创建新数据帧时,更改新数据帧:
什么时候会改变原来的使用 .loc/.iloc 进行标量/切片索引来创建新的数据帧.
Will not改变原来的时候使用 .loc 进行布尔索引,.query(), or .copy()用于创建新的数据框


这是 pandas 中有点令人困惑甚至令人沮丧的部分,但在大多数情况下,如果您遵循一些简单的工作流程规则,您实际上不必担心这一点。特别要注意的是,当您有两个数据帧时,这里只有两种一般情况,其中一个是另一个数据帧的子集。

在这种情况下,Python 禅宗规则“显式优于隐式”是一个值得遵循的重要指导原则。

案例 A:更改为df2不应该影响df1

当然,这是微不足道的。您需要两个完全独立的数据帧,因此您只需显式制作一个副本:

df2 = df1.copy()

在此之后你所做的任何事情df2仅影响df2并不是df1反之亦然。

案例 B:更改为df2也应该影响df1

在这种情况下,我认为没有一种通用的方法可以解决问题,因为这完全取决于您想要做什么。然而,有一些非常简单的标准方法,并且它们的工作原理不应该有任何含糊之处。

方法一:将df1复制到df2,然后使用df2更新df1

在这种情况下,您基本上可以对上面的示例进行一对一的转换。这是示例#2:

df2 = df1.copy()
df2 = df1.query('A < 10')
df2.iloc[0,1] = 100

df1 = df2.append(df1).reset_index().drop_duplicates(subset='index').drop(columns='index')

不幸的是重新合并通过append那里有点冗长。您可以使用以下命令更干净地完成此操作,尽管它具有将整数转换为浮点数的副作用。

df1.update(df2)   # note that this is an inplace operation

方法 2:使用掩码(不要创建df2 at all)

我认为这里最好的一般方法是不要创建df2根本没有,而是让它成为一个蒙版版本df1。有点不幸的是,您无法直接翻译上述代码,因为它混合了loc and iloc这对于这个例子来说很好,但对于实际使用来说可能不切实际。

优点是可以编写非常简单且可读的代码。这是上面示例 #2 的替代版本,其中df2实际上只是一个蒙版版本df1。但不是通过改变iloc,如果列“C”== 10,我将更改。

df2_mask = df1['A'] < 10
df1.loc[ df2_mask & (df1['C'] == 10), 'B'] = 100

现在如果你打印df1 or df1[df2_mask]您将看到每个数据帧的第一行的“B”列 = 100。显然,这并不奇怪,但这就是遵循“显式优于隐式”的固有优势。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Pandas:了解操作何时影响原始数据帧 的相关文章

  • Pycharm Python 控制台不打印输出

    我有一个从 Pycharm python 控制台调用的函数 但没有显示输出 In 2 def problem1 6 for i in range 1 101 2 print i end In 3 problem1 6 In 4 另一方面 像
  • 如何收集列表、字典等中重复计算的结果(或制作修改每个元素的列表的副本)?

    There are a great many existing Q A on Stack Overflow on this general theme but they are all either poor quality typical
  • 如何在android上的python kivy中关闭应用程序后使服务继续工作

    我希望我的服务在关闭应用程序后继续工作 但我做不到 我听说我应该使用startForeground 但如何在Python中做到这一点呢 应用程序代码 from kivy app import App from kivy uix floatl
  • Flask 和 uWSGI - 无法加载应用程序 0 (mountpoint='')(找不到可调用或导入错误)

    当我尝试使用 uWSGI 启动 Flask 时 出现以下错误 我是这样开始的 gt cd gt root localhost uwsgi socket 127 0 0 1 6000 file path to folder run py ca
  • pandas 替换多个值

    以下是示例数据框 gt gt gt df pd DataFrame a 1 1 1 2 2 b 11 22 33 44 55 gt gt gt df a b 0 1 11 1 1 22 2 1 33 3 2 44 4 3 55 现在我想根据
  • 如何等到 Excel 计算公式后再继续 win32com

    我有一个 win32com Python 脚本 它将多个 Excel 文件合并到电子表格中并将其另存为 PDF 现在的工作原理是输出几乎都是 NAME 因为文件是在计算 Excel 文件内容之前输出的 这可能需要一分钟 如何强制工作簿计算值
  • 安装后 Anaconda 提示损坏

    我刚刚安装张量流GPU创建单独的后环境按照以下指示here https github com antoniosehk keras tensorflow windows installation 但是 安装后当我关闭提示窗口并打开新航站楼弹出
  • python pandas 中的双端队列

    我正在使用Python的deque 实现一个简单的循环缓冲区 from collections import deque import numpy as np test sequence np array range 100 2 resha
  • Abaqus 将曲面转化为集合

    我一直试图在模型中找到两个表面的中心 参见照片 但未能成功 它们是元素表面 面 查询中没有选项可以查找元素表面的中心 只能查找元素集的中心 找到节点集的中心也很好 但是我的节点集没有出现在工具 gt 查询 gt 质量属性选项中 而且我找不到
  • Pandas Dataframe 中 bool 值的条件前向填充

    问题 如何转发 fill boolTruepandas 数据框中的值 如果是当天的第一个条目 True 到一天结束时 请参阅以下示例和所需的输出 Data import pandas as pd import numpy as np df
  • 表达式中的 Python 'in' 关键字与 for 循环中的比较 [重复]

    这个问题在这里已经有答案了 我明白什么是in运算符在此代码中执行的操作 some list 1 2 3 4 5 print 2 in some list 我也明白i将采用此代码中列表的每个值 for i in 1 2 3 4 5 print
  • Python:尝试检查有效的电话号码

    我正在尝试编写一个接受以下格式的电话号码的程序XXX XXX XXXX并将条目中的任何字母翻译为其相应的数字 现在我有了这个 如果启动不正确 它将允许您重新输入正确的数字 然后它会翻译输入的原始数字 我该如何解决 def main phon
  • 循环中断打破tqdm

    下面的简单代码使用tqdm https github com tqdm tqdm在循环迭代时显示进度条 import tqdm for f in tqdm tqdm range 100000000 if f gt 100000000 4 b
  • Python - 按月对日期进行分组

    这是一个简单的问题 起初我认为很简单而忽略了它 一个小时过去了 我不太确定 所以 我有一个Python列表datetime对象 我想用图表来表示它们 x 值是年份和月份 y 值是此列表中本月发生的日期对象的数量 也许一个例子可以更好地证明这
  • Numpy 优化

    我有一个根据条件分配值的函数 我的数据集大小通常在 30 50k 范围内 我不确定这是否是使用 numpy 的正确方法 但是当数字超过 5k 时 它会变得非常慢 有没有更好的方法让它更快 import numpy as np N 5000
  • 通过数据框与函数进行交互

    如果我有这样的日期框架 氮 EG 00 04 NEG 04 08 NEG 08 12 NEG 12 16 NEG 16 20 NEG 20 24 datum von 2017 10 12 21 69 15 36 0 87 1 42 0 76
  • Python 3 中“map”类型的对象没有 len()

    我在使用 Python 3 时遇到问题 我得到了 Python 2 7 代码 目前我正在尝试更新它 我收到错误 类型错误 map 类型的对象没有 len 在这部分 str len seed candidates 在我像这样初始化它之前 se
  • 从 Python 中的类元信息对 __init__ 函数进行类型提示

    我想做的是复制什么SQLAlchemy确实 以其DeclarativeMeta班级 有了这段代码 from sqlalchemy import Column Integer String from sqlalchemy ext declar
  • Python - 字典和列表相交

    给定以下数据结构 找出这两种数据结构共有的交集键的最有效方法是什么 dict1 2A 3A 4B list1 2A 4B Expected output 2A 4B 如果这也能产生更快的输出 我可以将列表 不是 dict1 组织到任何其他数
  • Python:元类属性有时会覆盖类属性?

    下面代码的结果让我感到困惑 class MyClass type property def a self return 1 class MyObject object metaclass MyClass a 2 print MyObject

随机推荐

  • 有 PostSharp 替代品吗? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我必须放弃使用 PostSharp 因为它不适用于混淆 合并的程序集 至少 我没有看到任何方法让它工作
  • 如何在 Python 3.x 中删除字符串末尾的数字?

    我想从字符串末尾删除数字 但我不知道 Can the split 方法工作 我怎样才能做到这一点 初始字符串看起来像asdfg123 而我只想asdfg反而 感谢您的帮助 不 split 不起作用 因为 split 只能与要分割的固定字符串
  • 从vue中的api加载路由

    我正在尝试从我的 API 在 Vue 应用程序中加载路由 我尝试将数据推送到路由变量并使用 addRoutes 方法 但没有运气 我认为异步可能存在问题 但为什么 addRoutes 不起作用 这是我的代码 import Vue from
  • 如何使用界面生成器在 UITableView 中设置水平滚动?

    我的应用程序中有 UITableView 有 2 列 我可以阅读第 1 列和第 2 列的一半 我的问题是 我们可以使用 uitableview 中的界面生成器添加水平滚动 以便我可以读取表中所有单元格的第 2 列吗 我们是否也必须为此添加一
  • 为什么 Task.WhenAny 没有抛出预期的 TimeoutException?

    请注意以下简单代码 class Program static void Main var sw new Stopwatch sw Start try Task WhenAny RunAsync GetAwaiter GetResult ca
  • PHP/MySQL/jQuery 记录的悲观锁定

    我一直在考虑为我参与的应用程序开发一些简单的记录锁定 有一些用户实际上需要花费几个小时才能完成记录的编辑 当其他人想要更改记录时 这会导致问题 目前不涉及锁定 我不确定乐观锁定在我的情况下是否可靠 因为记录是通过 AJAX 请求保存的 我正
  • C++ 中类定义的顺序

    我这里有点问题 我试图定义几个类 其中一些是玩家 一些是属于玩家的 Pawn 来自 Python 我习惯于能够通过 Pawn 方便地访问 Pawn 拥有的 Player 以及通过 Player 访问 Player 的 Pawn 如果我错了请
  • android logcat 记录闲聊模块行过期消息

    我收到很多与我的应用程序相关的此类 logcat 消息 11 19 19 04 23 872 3327 3440 I chatty uid 10085 com xxxx yyy expire 18 lines 这些日志消息是什么 我在这里缺
  • 如何使用索引优化 InnoDB 上的 COUNT(*) 性能

    我有一个较大但狭窄的 InnoDB 表 有大约 9m 条记录 正在做count or count id 桌子上的速度非常慢 6秒以上 DROP TABLE IF EXISTS perf2 CREATE TABLE perf2 id int
  • 如何选择按范围分组的值的计数

    斯塔克万岁 我需要选择按范围分组的值的计数 举例来说 假设我在表列中有以下值 1 2 4 5 6 8 9 11 13 16 然后 我想检索 5 范围内它们的计数 如下所示 From 0 to 4 there is 3 values 1 2
  • 在 Process Explorer 中调试 RtlUserThreadStart

    我有一个基于 3 5 构建的多线程 wpf 应用程序 当我通过 Process Explorer 查看正在运行的线程时 我看到 8 个线程都具有相同的起始地址 ntdll dll RtlUserThreadStart 并且所有 8 个线程的
  • emacs中如何删除重复行

    我的文本有很多行 我的问题是如何删除 emacs 中的重复行 在没有外部实用程序的情况下使用 emacs 或 elisp 包中的命令 例如 this is line a this is line b this is line a 删除第三行
  • 如何让 Kotlin 类型安全构建器在 Scala 中工作?

    Kotlin 很棒类型安全的构建者 https kotlinlang org docs reference type safe builders html这使得创建像这样的 dsl 成为可能 html head title The titl
  • 如何启动 java-web-start 应用程序并等待其退出?

    我刚刚发现javaws wait没有做 Windows 上应该做的事情 它将在应用程序完成之前返回 这个 bug 已经存在 5 年多了 并且已关闭 无法修复6281477 https bugs java com bugdatabase vi
  • 如何在 ubuntu 上的 emacs 中运行 shell 命令,同时避免 bash 作业控制错误?

    我在 ubuntu 中安装了 emacs 使用 sudo apt get install emacs 我遇到的问题是 当我尝试从 emacs 中运行 shell 命令时 例如M ls 输出之前是这样的 bash cannot set ter
  • 使用外源数据进行 SARIMAX 样本外预测

    我正在使用 SARIMAX 进行时间序列分析 并且一直在努力解决这个问题 我想我已经成功地拟合了一个模型并用它来进行预测 但是 我不知道如何利用外源数据进行样本预测 我可能做错了整个事情 所以我在下面包含了我的步骤和一些示例数据 impor
  • 如何使用 JDBC 将大型(或至少是重要的)BLOB 放入 Oracle 中?

    我正在开发一个应用程序来执行一些批处理 并且希望将输入和输出数据作为文件存储在 Oracle 数据库的 BLOB 字段中 Oracle版本是10g r2 使用如下的PreparedStatement setBinaryStream 方法会将
  • 应用程序包包含本机代码,我找不到调试符号 .zip

    这是关于 PlayStore 警告调试符号 添加行到 build gradle app 后我已成功构建 Gradle android buildTypes release ndk debugSymbolLevel FULL 但遵循指示htt
  • 使用 Mongoose 多次查询,无需嵌套

    我正在尝试使用 node js 生成一个文档 该文档需要从 mongo 数据库运行多个不相关的数据库查询 这是我当前的代码 Data find function err results if err return next err fini
  • Pandas:了解操作何时影响原始数据帧

    我喜欢 pandas 并且已经使用它很多年了 并且非常有信心我能够很好地掌握如何对数据帧进行子集化并适当地处理视图与副本 尽管我使用了很多断言来确保 我还知道有很多关于SettingWithCopyWarning的问题 例如如何处理Pand