在操作数据的时候,DataFrame对象中删除一个或多个列是常见的操作,并且实现方法较多,然而这中间有很多细节值得关注。

首先,一般被认为是“正确”的方法,是使用DataFramedrop方法,之所以这种方法被认为是标准的方法,可能是收到了SQL语句中使用drop实现删除操作的影响。

import pandas as pd
import numpy as npdf = pd.DataFrame(np.arange(25).reshape((5,5)), columns=list("abcde"))display(df)try:df.drop('b')
except KeyError as ke:print(ke)
    a   b   c   d   e
0   0   1   2   3   4
1   5   6   7   8   9
2  10  11  12  13  14
3  15  16  17  18  19
4  20  21  22  23  24
"['b'] not found in axis"

上面的操作中出现了报错信息,什么原因?这是因为drop方法中,默认是删除行。

如果用axis=0axis='rows',都表示展出行,也可用labels参数删除行。

df.drop(0)                # drop a row, on axis 0 or 'rows'
df.drop(0, axis=0)        # same
df.drop(0, axis='rows')   # same
df.drop(labels=0)         # same
df.drop(labels=[0])       # same# 结果a   b   c   d   e
1   5   6   7   8   9
2  10  11  12  13  14
3  15  16  17  18  19
4  20  21  22  23  24

如何删除列

如何删除列?可以指定axis或使用columns参数,如下所示:

df.drop('b', axis=1)         # drop a column
df.drop('b', axis='columns') # same
df.drop(columns='b')         # same
df.drop(columns=['b'])       # same# 输出a   c   d   e
0   0   2   3   4
1   5   7   8   9
2  10  12  13  14
3  15  17  18  19
4  20  22  23  24

这样就删除了一列,注意,删除之后,返回了新的对象,这意味着,你可以用一个新的变量引用删除后得到的结果。如果要改变原有的DataFrame,可以增加一个参数inplace=True

df2 = df.drop('b', axis=1)print(df2.columns)
print(df.columns)# result
Index(['a', 'c', 'd', 'e'], dtype='object')
Index(['a', 'b', 'c', 'd', 'e'], dtype='object')

同样值得注意的是,你可以通过同时使用indexcolumns,同时删除行和列,并且你可以传入多个值,即删除多行或者多列。

df.drop(index=[0,2], columns=['b','c'])# resulta   d   e
1   5   8   9
3  15  18  19
4  20  23  24

如果不使用drop方法,还可以通过索引实现同样的操作。有多种方式,这里列举一种,如下所示,用.loc.isin并取反。

df.loc[~df.index.isin([0,2]), ~df.columns.isin(['b', 'c'])]# resulta   d   e
1   5   8   9
3  15  18  19
4  20  23  24

If none of that makes sense to you, I would suggest reading through my series on selecting and indexing in pandas, starting here.

如果这些对你来说都不是很清楚,建议参阅《跟老齐学Python:数据分析》中对此的详细说明。

另外的方法

除了上面演示的方法之外,还有别的方法可以删除列。

del df['a']
df# resultb   c   d   e
0   1   2   3   4
1   6   7   8   9
2  11  12  13  14
3  16  17  18  19
4  21  22  23  24

原来的df['a']没了,这就如同前面用drop方法时参数中使用了inplace=True一样,原地修改。

但是,不要认为del就能百试百灵,它会让你有迷茫的时候。

我们知道,如果用类似df.b这样访问属性的形式,也能得到DataFrame对象的列,虽然这种方法我不是很提倡使用,但很多数据科学的民工都这么干。

df.b# result
0     1
1     6
2    11
3    16
4    21
Name: b, dtype: int64

这么干,如果仅仅是查看,也无所谓,但是:

del df.b# result
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-10-0dca358a6ef9> in <module>
----> 1 del df.bAttributeError: b

这就报错了。是不是很迷惑,为什del df['b']奏效,而del df.b无效?

这就是接下来要研究的了。必须通过对细节的剖析,才能搞清楚问题的根源。

首先,del df['b']有效,是因为DataFrame对象中实现了__delitem__方法,在执行del df['b']时会调用该方法。但是del df.b呢,有没有调用此方法呢?

为此,可以定义一个简单的类,这里暂用dict作为保存数据的容器,当然,这个类不是真正的DataFrame

class StupidFrame:def __init__(self, columns):self.columns = columnsdef __delitem__(self, item):del self.columns[item]def __getitem__(self, item):return self.columns[item]def __setitem__(self, item, val):self.columns[item] = valf = StupidFrame({'a': 1, 'b': 2, 'c': 3})
print("StupidFrame value for a:", f['a'])
print("StupidFrame columns: ", f.columns)
del f['b']
f.d = 4
print("StupidFrame columns: ", f.columns)# result
StupidFrame value for a: 1
StupidFrame columns:  {'a': 1, 'b': 2, 'c': 3}
StupidFrame columns:  {'a': 1, 'c': 3}

认真观察上面的操作和StupidFrame代码,如果用[]对所创建的实例进行数据操作,可以实现删除、赋值、读取等。但是,当我们执行f.d = 4的操作时,并没有在StupidFrame中所创建的columns属性中增加键为d的键值对,而是为实例f增加了一个普通属性,名称是d

因此,如果要让f.df['d']等效,还必须要在StupidFrame类中添加 __getattr__ 方法,并使用__setattr__方法来处理设置问题(关于这两个方法的使用,请参阅《Python大学实用教程》中的详细介绍)。

class StupidFrameAttr:def __init__(self, columns):self.__dict__['columns'] = columnsdef __delitem__(self, item):del self.__dict__['columns'][item]def __getitem__(self, item):return self.__dict__['columns'][item]def __setitem__(self, item, val):self.__dict__['columns'][item] = valdef __getattr__(self, item):if item in self.__dict__['columns']:return self.__dict__['columns'][item]elif item == 'columns':return self.__dict__[item]else:raise AttributeErrordef __setattr__(self, item, val):if item != 'columns':self.__dict__['columns'][item] = valelse:raise ValueError("Overwriting columns prohibited") f = StupidFrameAttr({'a': 1, 'b': 2, 'c': 3})
print("StupidFrameAttr value for a", f['a'])
print("StupidFrameAttr columns: ", f.columns)
del f['b']
print("StupidFrameAttr columns: ", f.columns)
print("StupidFrameAttr value for a", f.a)
f.d = 4
print("StupidFrameAttr columns: ", f.columns)
del f['d']
print("StupidFrameAttr columns: ", f.columns)
f.d = 5
print("StupidFrameAttr columns: ", f.columns)
del f.d# result
StupidFrameAttr value for a 1
StupidFrameAttr columns:  {'a': 1, 'b': 2, 'c': 3}
StupidFrameAttr columns:  {'a': 1, 'c': 3}
StupidFrameAttr value for a 1
StupidFrameAttr columns:  {'a': 1, 'c': 3, 'd': 4}
StupidFrameAttr columns:  {'a': 1, 'c': 3}
StupidFrameAttr columns:  {'a': 1, 'c': 3, 'd': 5}
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-12-fd29f59ea01e> in <module>39 f.d = 540 print("StupidFrameAttr columns: ", f.columns)
---> 41 del f.dAttributeError: d

现在删除属性也能够奏效了。

另外,还可以在类中重写__delattr__方法,如下所示:

class StupidFrameDelAttr(StupidFrameAttr):def __delattr__(self, item):# trivial implementation using the data model methodsdel self.__dict__['columns'][item]f = StupidFrameDelAttr({'a': 1, 'b': 2, 'c': 3})
print("StupidFrameDelAttr value for a", f['a'])
print("StupidFrameDelAttr columns: ", f.columns)
del f['b']
print("StupidFrameDelAttr columns: ", f.columns)
print("StupidFrameDelAttr value for a", f.a)
f.d = 4
print("StupidFrameDelAttr columns: ", f.columns)
del f.d
print("StupidFrameDelAttr columns: ", f.columns)# result
StupidFrameDelAttr value for a 1
StupidFrameDelAttr columns:  {'a': 1, 'b': 2, 'c': 3}
StupidFrameDelAttr columns:  {'a': 1, 'c': 3}
StupidFrameDelAttr value for a 1
StupidFrameDelAttr columns:  {'a': 1, 'c': 3, 'd': 4}
StupidFrameDelAttr columns:  {'a': 1, 'c': 3}

现在,就理解了前面使用del删除DataFrame对象属性的方法出问题的根源了。当然,并不是说DataFrame对象的类就是上面那样的,而是用上面的方式简要说明了一下原因。

所以,在Pandas中要删除DataFrame的列,最好是用对象的drop方法。

另外,特别提醒,如果要创建新的列,也不要用df.column_name的方法,这也容易出问题。

参考文献

[1]. https://www.wrighters.io/how-to-remove-a-column-from-a-dataframe/

从DataFrame中删除列相关推荐

  1. python从DataFrame中删除列

    目录 在操作数据的时候, DataFrame 对象中删除一个或多个列是常见的操作,并且实现方法较多,然而这中间有很多细节值得关注. 首先,一般被认为是"正确"的方法,是使用 Dat ...

  2. pandas使用dropna函数删除dataframe中全是缺失值的数据列(drop columns with all missing values in dataframe)

    pandas使用dropna函数删除dataframe中全是缺失值的数据列(drop columns with all missing values in dataframe) 目录

  3. pandas基于dataframe字符串数据列不包含特定字符串来筛选dataframe中的数据行(rows where values do not contain substring)

    pandas基于dataframe字符串数据列不包含(not contains)特定字符串来筛选dataframe中的数据行(rows where values do not contain subs ...

  4. R语言ggplot2可视化:使用geom_line函数将dataframe中数据可视化为时间序列(或折线图)(Time Series Plot From a Data Frame)、添加标题、副标题

    R语言ggplot2可视化:使用geom_line函数将dataframe中数据可视化为时间序列(或折线图)(Time Series Plot From a Data Frame).添加标题.副标题. ...

  5. pandas使用str函数和startswith函数,筛选dataframe中不是(not start with)以特定前缀开头的数据列(selecting columns)

    pandas使用str函数和startswith函数,筛选dataframe中不是(not start with)以特定前缀开头的数据列(selecting columns not begin wit ...

  6. pandas索引复合索引dataframe数据、索引dataframe中指定行和指定列交叉格子的数据内容(getting a specific value)、使用元组tuple表达复合索引的指定行

    pandas索引复合索引dataframe数据.索引dataframe中指定行和指定列交叉格子的数据内容(getting a specific value).使用元组tuple表达复合索引的指定行 目 ...

  7. pandas使用rename函数重命名dataframe中数据列的名称、从而创建一个包含重复列名称的dataframe数据集

    pandas使用rename函数重命名dataframe中数据列的名称.从而创建一个包含重复列名称的dataframe数据集 目录

  8. pandas使用query函数删除dataframe中某一列数值小于某一特定值的行(remove dataframe rows baed on column value)

    pandas使用query函数删除dataframe中某一列数值小于某一特定值的行(remove dataframe rows baed on column value) 目录

  9. pandas使用方括号[]或者loc函数、基于列名称或者列名称列表索引dataframe中的单个数据列或者多个数据列(accessing columns of a dataframe)

    pandas使用方括号[]或者loc函数.基于列名称或者列名称列表索引dataframe中的单个数据列或者多个数据列(accessing columns of a dataframe using co ...

最新文章

  1. 2019年中国科创板全面解读报告
  2. 一个为制造业而生的AI助手,普通员工向它提问就能做数据分析
  3. android studio无线真机调试
  4. 这里有 8 个流行的 Python 可视化工具包,你喜欢哪个?
  5. 2013\National _C_C++_A\2.骰子迷题
  6. POJ3320 Jessica's Reading Problem 尺取法
  7. Android、iOS平台RTMP/RTSP播放器实现实时音量调节
  8. 小强的HTML5移动开发之路(50)——jquerymobile页面初始化过程
  9. python在生活中有哪些用处-Python语言有哪些用途
  10. C# DateTime类
  11. 【7001】n阶法雷序列
  12. 用python写个类似浏览器的下载器,超简单的
  13. 软件系统演示脚本实践(草稿)
  14. 【Arc GIS 零基础教学】常用的环境科学与工程专业英语词汇分享
  15. 关于“缓存着色(cache coloring, page coloring)”技术的相关资料介绍
  16. 用标签打印软件将Excel中的多列数据合并打印
  17. 天刀显示服务器失败,天涯明月刀手游提示安装失败怎么办 10月16日开服常见问题FAQ...
  18. Vue源码剖析(一):抽离AST抽象语法树
  19. 从零开始的单片机学习(二)
  20. 分享AI前端硬件识别4G摄像头模组方案

热门文章

  1. SQL DEFAULT
  2. 尚硅谷 家庭收支记账软件
  3. datagrid-detailview 使用总结
  4. C#实现发送钉钉工作通知消息
  5. python 实现字典_Python字典实现
  6. linux 修改文件内容sed,linux下通过sed命令直接修改文件内容
  7. 疫情期间生活情况分析
  8. ASP.NET MVC 框架
  9. 正点原子USMART使用
  10. oracle默认用户的密码,Oracle的默认用户密码