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:了解操作何时影响原始数据帧 的相关文章

随机推荐

  • 有 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