从 pandas DataFrame 删除列

在删除 DataFrame 中的列时,我使用:

del df['column_name']

这很棒。为什么不能使用以下内容?

del df.column_name

因为您可以使用df.column_name来访问列 / 系列, df.column_name我希望这可以正常工作。

答案

在熊猫中做到这一点的最好方法是使用drop

df = df.drop('column_name', 1)

其中1编号( 0代表行, 1代表列)。

要删除该列而不必重新分配df您可以执行以下操作:

df.drop('column_name', axis=1, inplace=True)

最后,要按列而不是按列标签删除,请尝试将其删除,例如第一,第二和第四列:

df = df.drop(df.columns[[0, 1, 3]], axis=1)  # df.columns is zero-based pd.Index

还可以对列使用 “文本” 语法:

df.drop(['column_nameA', 'column_nameB'], axis=1, inplace=True)

如您所料,正确的语法是

del df['column_name']

仅仅由于 Python 的语法限制,很难使del df.column_name起作用。 Python 将del df[name]转换为df.__delitem__(name)

采用:

columns = ['Col1', 'Col2', ...]
df.drop(columns, inplace=True, axis=1)

这将就地删除一个或多个列。请注意, inplace=True已在 pandas v0.13 中添加,不适用于旧版本。在这种情况下,您必须将结果分配回去:

df = df.drop(columns, axis=1)

按索引下降

删除第一,第二和第四列:

df.drop(df.columns[[0,1,3]], axis=1, inplace=True)

删除第一列:

df.drop(df.columns[[0]], axis=1, inplace=True)

有一个可选参数inplace使原来的数据可以不创建副本被修改。

弹出

列选择,添加,删除

删除列column-name

df.pop('column-name')

例子:

df = DataFrame.from_items([('A', [1, 2, 3]), ('B', [4, 5, 6]), ('C', [7,8, 9])], orient='index', columns=['one', 'two', 'three'])

print df

one  two  three
A    1    2      3
B    4    5      6
C    7    8      9

df.drop(df.columns[[0]], axis=1, inplace=True) print df

two  three
A    2      3
B    5      6
C    8      9

three = df.pop('three') print df

two
A    2
B    5
C    8

此处提出的实际问题是大多数答案都遗漏的:

为什么不能使用del df.column_name

首先,我们需要了解问题,这需要我们深入研究Python 魔术方法

正如 Wes 在他的回答中指出的那样, del df['column']映射到 python 魔术方法 df.__delitem__('column') ,该方法在熊猫中实现,用于删除列

但是,正如上面有关python 魔术方法的链接所指出的:

实际上, __del__几乎永远不应该被使用,因为它在不稳定的环境中被使用。谨慎使用!

您可能会争辩说,不应使用或鼓励使用del df['column_name'] ,因此甚至不应考虑使用del df.column_name

但是,从理论上讲,可以使用魔术方法__delattr__实现del df.column_name在熊猫中工作。但是,这确实会带来某些问题,即del df['column_name']实现已经存在的问题,但程度较小。

示例问题

如果我在称为 “dtypes” 或 “columns” 的数据框中定义一列怎么办。

然后假设我要删除这些列。

del df.dtypes会使__delattr__方法感到困惑,好像它应该删除 “dtypes” 属性或 “dtypes” 列一样。

这个问题背后的架构问题

  1. 数据框是的集合吗?
  2. 数据框是的集合吗?
  3. 列是数据框的属性吗?

熊猫答案:

  1. 是的,在所有方面
  2. 不,但是如果您愿意,可以使用.ix.loc.iloc方法。
  3. 也许,您想读取数据吗?然后除非该属性的名称已被属于该数据帧的另一个属性采用。您要修改数据吗?那不行

TLDR;

您不能使用del df.column_name因为熊猫的结构非常疯狂,需要重新考虑,以免用户出现这种认知失调

专家提示:

不要使用 df.column_name,它可能很漂亮,但是会导致认知失调

适用于以下情况的 Python Zen 报价:

删除列有多种方法。

应该有一种 - 最好只有一种 - 显而易见的方法。

列有时是属性,但有时不是。

特殊情况还不足以打破规则。

del df.dtypes是否删除 dtypes 属性或 dtypes 列?

面对模棱两可的想法,拒绝猜测的诱惑。

一个不错的附加功能是仅在存在列时才删除列的功能。这样,您可以涵盖更多用例,并且只会从传递给它的标签中删除现有列:

例如,只需添加errors ='ignore' ::

df.drop(['col_name_1', 'col_name_2', ..., 'col_name_N'], inplace=True, axis=1, errors='ignore')
  • 这是从熊猫 0.16.1 开始的新功能。文档在这里

从 0.16.1 版本开始就可以

df.drop(['column_name'], axis = 1, inplace = True, errors = 'ignore')

始终使用[]表示法是一种好习惯。原因之一是属性符号( df.column_name )对编号索引不起作用:

In [1]: df = DataFrame([[1, 2, 3], [4, 5, 6]])

In [2]: df[1]
Out[2]:
0    2
1    5
Name: 1

In [3]: df.1
  File "<ipython-input-3-e4803c0d1066>", line 1
    df.1
       ^
SyntaxError: invalid syntax

熊猫 0.21 + 答案

Pandas 版本 0.21 略微更改了drop方法,以包括indexcolumns参数,以匹配renamereindex方法的签名。

df.drop(columns=['column_a', 'column_c'])

就个人而言,我更喜欢使用axis参数表示列或索引,因为它是几乎所有 pandas 方法中使用的主要关键字参数。但是,现在您在 0.21 版中有了一些附加选择。

在 pandas 0.16.1 + 中,只有按照 @eiTanLaVi 发布的解决方案存在的情况下,才能删除列。在该版本之前,您可以通过条件列表理解来获得相同的结果:

df.drop([col for col in ['col_name_1','col_name_2',...,'col_name_N'] if col in df], 
        axis=1, inplace=True)