专栏首页机器学习与统计学Pandas切片操作:一个很容易忽视的错误

Pandas切片操作:一个很容易忽视的错误

Pandas是一个强大的分析结构化数据的工具集,主要用于数据挖掘和数据分析,同时也提供数据清洗功能。

很多初学者在数据的选取,修改和切片时经常面临一些困惑。这是因为Pandas提供了太多方法可以做同样的事情,方法选择不当,可能导致一些意想不到的错误。

Pandas切片

Pandas数据访问方式包括:df[] ,.at,.iat,.loc,.iloc(之前有ix方法,pandas1.0之后已被移除)

  • df[] :直接索引
  • at/iat:通过标签或行号获取某个数值的具体位置。
  • loc:通过标签选取数据,即通过index和columns的值进行选取。loc方法有两个参数,按顺序控制行列选取,范围包括start和end。
  • iloc:通过行号选取数据,即通过数据所在的自然行列数为选取数据。iloc方法也有两个参数,按顺序控制行列选取。

它们之间的区别不是文本重点,大家可以新建一个dataframe练习一下,本文我们主要来一个错误示范,然后给大家提一些合理的建议。

错误示范

新建一个DataFrame

df = pd.DataFrame(
{'x':[1,5,4,3,4,5],
'y':[.1,.5,.4,.3,.4,.5],
'w':[11,15,14,13,14,15]})

   x    y   w
0  1  0.1  11
1  5  0.5  15
2  4  0.4  14
3  3  0.3  13
4  4  0.4  14
5  5  0.5  15

假设我们要查找与“x”列对应的所有DataFrame元素都大于3,并根据此更改将所有对应的“ y”值更改为50。 我们来先试一个看起来毫无问题的方法

df[df['x']>3]['y']=50 运行之后,df没有任何变化,Warning如下:

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

根据提示信息,我们使用loc方法

df.loc[df['x']>3,'y']=50
   x     y   w
0  1   0.1  11
1  5  50.0  15
2  4  50.0  14
3  3   0.3  13
4  4  50.0  14
5  5  50.0  15

得到预期结果√

这是为什么呢?这里我们就遇到了所谓的“链接索引”,具体原因是使用了两个索引器,例如:df[][] df[df['x']>3] 导致Pandas创建原始DataFrame的单独副本 df[df['x']>3]['y'] = 50 将新值分配给“ y”列,但在此临时创建的副本上,而不是原始DataFrame上。

反转切片的顺序时,即先调用列,然后再调用我们要满足的条件,便得到了预期的结果:

df['y'][df['x']>3]=50

   x     y   w
0  1   0.1  11
1  5  50.0  15
2  4  50.0  14
3  3   0.3  13
4  4  50.0  14
5  5  50.0  15

但是同样会给出一个Warning:A value is trying to be set on a copy of a slice from a DataFrame

SettingWithCopyWarning 是一个警告 Warning,而不是错误 Error。这是因为,当我们从DataFrame中仅选择一列时,Pandas会创建一个视图,而不是副本。关于视图和副本的区别,下图最为形象:

df[]方法会创建视图

df
   x    y   w
0  1  0.1  11
1  5  0.5  15
2  4  0.4  14
3  3  0.3  13
4  4  0.4  14
5  5  0.5  15

z = df['y'] # view of column 'y'
z[z>=0.5] = 30

z
0     0.1
1    30.0
2     0.4
3     0.3
4     0.4
5    30.0

df
   x     y   w
0  1   0.1  11
1  5  30.0  15
2  4   0.4  14
3  3   0.3  13
4  4   0.4  14
5  5  30.0  15

当我们创建了视图后,pandas就会出现warning,因为它不知道我们是否只想更改y系列(通过z)或原始值df。如果我们要提取“z”作为独立对象怎么办?pandas提供了copy()方法,当我们将命令更新为以下所示的命令时:

z = df['y'].copy()

我们将在内存中创建一个具有其自己地址的全新对象,并且对“z”进行的任何更新df都将不受影响。实际上有两个要点,可以使我们在使用切片和数据操作时免受任何有害影响:

  • 避免链接索引,始终选择.loc/ .iloc(或.at/ .iat)方法;
  • 使用copy() 创建独立的对象,并保护原始资源免遭不当操纵

参考

https://www.jianshu.com/p/199a653e9668 https://www.kdnuggets.com/2020/04/stop-hurting-pandas.html

本文分享自微信公众号 - 机器学习与统计学(tjxj666),作者:爱学习的胡同学

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-05-06

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 私藏的5个好用的Pandas函数!

    explode用于将一行数据展开成多行。比如说dataframe中某一行其中一个元素包含多个同类型的数据,若想要展开成多行进行分析,这时候explode就派上用...

    统计学家
  • 数据分析最有用的25个 Matplotlib图

    50个Matplotlib图的汇编,在数据分析和可视化中最有用。此列表允许您使用Python的Matplotlib和Seaborn库选择要显示的可视化对象。

    统计学家
  • 8个用于数据清洗的Python代码

    数据清洗,是进行数据分析和使用数据训练模型的必经之路,也是最耗费数据科学家/程序员精力的地方。

    统计学家
  • 8个Python高效数据分析的技巧

    厌倦了定义用不了几次的函数? Lambda表达式是你的救星! Lambda表达式用于在Python中创建小型,一次性和匿名函数对象。 它能替你创建一个函数。

    用户2966292
  • 3. Pandas系列 - DataFrame操作

    计算广告生态
  • 8 个 Python 高效数据分析的技巧

    不管是参加Kaggle比赛,还是开发一个深度学习应用,第一步总是数据分析,这篇文章介绍了8个使用Python进行数据分析的方法,不仅能够提升运行效率,还能够使代...

    用户2769421
  • 这 8 个 Python 技巧让你的数据分析提升数倍!

    不管是参加Kaggle比赛,还是开发一个深度学习应用,第一步总是数据分析,这篇文章介绍了8个使用Python进行数据分析的方法,不仅能够提升运行效率,还能够使代...

    昱良
  • 《深入理解计算机系统》阅读笔记--程序的机器级表示(上)

    编译器基于编程语言的规则,目标机器的指令集和操作系统遵循的惯例,经过一系列的阶段生成机器代码。GCC c语言编译器以汇编代码的形式产生输出,汇编代码是机器代码的...

    coders
  • 数据库PostrageSQL-服务器配置资源消耗

    shared_buffers (integer) 设置数据库服务器将使用的共享内存缓冲区量。默认通常是 128 兆字节(128MB),但是如果你的内核设置不支...

    cwl_java
  • 《自然》杂志:注射一针,长效作用半年,艾滋新药在路上

    今天,《自然》杂志报道了吉利德科学(Gilead Sciences)生物医药公司研发的新型抗艾滋病毒的小分子药物。初步临床研究表明,单次给药后,可使艾滋病病毒感...

    用户6317549

扫码关注云+社区

领取腾讯云代金券