关于python:按列名从pandas数据框中删除列

Delete column from pandas DataFrame by column name

删除数据帧中的列时,我使用:

1
del df['column_name']

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

1
del df.column_name

由于您可以以df.column_name的形式访问列/系列,因此我希望这项工作能够正常进行。


在大熊猫中,最好的方法是使用drop

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

其中,1是轴号(行为0),列为1)。

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

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

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

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


正如您所猜测的,正确的语法是

1
del df['column_name']

由于Python中的语法限制,很难使del df.column_name简单地工作。在python的覆盖下,del df[name]被翻译成df.__delitem__(name)


用途:

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

这将在适当位置删除一个或多个列。请注意,在pandas v0.13中添加了inplace=True,不能在旧版本上工作。在这种情况下,您必须重新分配结果:

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


指数下降

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

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

删除第一列:

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

有一个可选参数inplace,以便可以在不创建副本的情况下修改数据。

被逮捕的

列选择、添加、删除

删除column-name列:

1
df.pop('column-name')

实例:

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

print df

1
2
3
4
   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

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

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

1
2
3
4
   two
A    2
B    5
C    8


大多数答案遗漏的实际问题是:

为什么我不能使用del df.column_name

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

正如Wes在他的回答中指出的那样,del df['column']映射到python magic方法df.__delitem__('column'),后者在pandas中实现以删除列。

但是,正如上面关于python magic方法的链接所指出的那样:

In fact, del should almost never be used because of the precarious circumstances under which it is called; use it with caution!

你可以说,不应该使用或鼓励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"列一样。

这个问题背后的架构问题

  • 是数据帧A列集合?
  • 数据帧是行的集合吗?
  • 列是数据帧的属性吗?
  • 熊猫回答:

  • 是的,在所有方面
  • 不,但是如果您想这样做,可以使用.ix.loc.iloc方法。
  • 也许,您想读取数据吗?然后是,除非属性的名称已经被属于数据帧的另一个属性所占用。是否要修改数据?然后没有。
  • TLDR;

    你不能做del df.column_name,因为熊猫有一个非常广泛的生长结构,需要重新考虑,以便这种认知失调不会发生在它的用户身上。

    Protip:

    不要使用df.column名称,它可能很漂亮,但它会导致认知失调。

    python的zen引用适合这里:

    删除列有多种方法。

    There should be one-- and preferably only one --obvious way to do it.

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

    Special cases aren't special enough to break the rules.

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

    In the face of ambiguity, refuse the temptation to guess.


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

    只需添加错误='ignore',例如:

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


    从0.16.1版开始

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


    总是使用[]符号是一种良好的做法。一个原因是属性表示法(df.column_name对编号索引无效:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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

    在pandas 0.16.1+中,只有当列存在时,才能根据@eitanlavi发布的解决方案删除列。在此版本之前,您可以通过条件列表理解来获得相同的结果:

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

    熊猫0.21+答案

    熊猫0.21版略微改变了drop方法,将indexcolumns参数都包括在内,以匹配renamereindex方法的签名。

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

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


    DR

    为找到一个稍微高效的解决方案付出了很多努力。在牺牲df.drop(dlst, 1, errors='ignore')的简单性的同时,很难证明增加的复杂性。

    1
    df.reindex_axis(np.setdiff1d(df.columns.values, dlst), 1)

    序言删除列在语义上与选择其他列相同。我将展示一些额外的方法来考虑。

    我还将重点介绍一次删除多个列以及允许尝试删除不存在的列的一般解决方案。

    使用这些解决方案是一般性的,并且对于简单的情况也适用。

    安装程序考虑pd.DataFramedf和要删除dlst的列表。

    1
    2
    df = pd.DataFrame(dict(zip('ABCDEFGHIJ', range(1, 11))), range(3))
    dlst = list('HIJKLM')
    1
    2
    3
    4
    5
    6
    df

       A  B  C  D  E  F  G  H  I   J
    0  1  2  3  4  5  6  7  8  9  10
    1  1  2  3  4  5  6  7  8  9  10
    2  1  2  3  4  5  6  7  8  9  10
    1
    2
    3
    dlst

    ['H', 'I', 'J', 'K', 'L', 'M']

    结果应该是:

    1
    2
    3
    4
    5
    6
    df.drop(dlst, 1, errors='ignore')

       A  B  C  D  E  F  G
    0  1  2  3  4  5  6  7
    1  1  2  3  4  5  6  7
    2  1  2  3  4  5  6  7

    因为我将删除一列等同于选择其他列,所以我将把它分成两种类型:

  • 标签选择
  • 布尔选择
  • 标签选择

    我们首先制造标签的列表/数组,这些标签表示我们想要保留的列,不包含我们想要删除的列。

  • df.columns.difference(dlst)

    1
    Index(['A', 'B', 'C', 'D', 'E', 'F', 'G'], dtype='object')
  • np.setdiff1d(df.columns.values, dlst)

    1
    array(['A', 'B', 'C', 'D', 'E', 'F', 'G'], dtype=object)
  • df.columns.drop(dlst, errors='ignore')

    1
    Index(['A', 'B', 'C', 'D', 'E', 'F', 'G'], dtype='object')
  • list(set(df.columns.values.tolist()).difference(dlst))

    1
    2
    # does not preserve order
    ['E', 'D', 'B', 'F', 'G', 'A', 'C']
  • [x for x in df.columns.values.tolist() if x not in dlst]

    1
    ['A', 'B', 'C', 'D', 'E', 'F', 'G']
  • 标签中的列为了比较选择过程,假设:

    1
     cols = [x for x in df.columns.values.tolist() if x not in dlst]

    然后我们可以评估

  • df.loc[:, cols]
  • df[cols]
  • df.reindex(columns=cols)
  • df.reindex_axis(cols, 1)
  • 所有评估结果如下:

    1
    2
    3
    4
       A  B  C  D  E  F  G
    0  1  2  3  4  5  6  7
    1  1  2  3  4  5  6  7
    2  1  2  3  4  5  6  7

    布尔切片

    我们可以构建一个用于切片的布尔数组/列表

  • ~df.columns.isin(dlst)
  • ~np.in1d(df.columns.values, dlst)
  • [x not in dlst for x in df.columns.values.tolist()]
  • (df.columns.values[:, None] != dlst).all(1)
  • 来自布尔值的列为了比较

    1
    bools = [x not in dlst for x in df.columns.values.tolist()]
  • df.loc[: bools]
  • 所有评估结果如下:

    1
    2
    3
    4
       A  B  C  D  E  F  G
    0  1  2  3  4  5  6  7
    1  1  2  3  4  5  6  7
    2  1  2  3  4  5  6  7

    鲁棒定时

    功能

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    setdiff1d = lambda df, dlst: np.setdiff1d(df.columns.values, dlst)
    difference = lambda df, dlst: df.columns.difference(dlst)
    columndrop = lambda df, dlst: df.columns.drop(dlst, errors='ignore')
    setdifflst = lambda df, dlst: list(set(df.columns.values.tolist()).difference(dlst))
    comprehension = lambda df, dlst: [x for x in df.columns.values.tolist() if x not in dlst]

    loc = lambda df, cols: df.loc[:, cols]
    slc = lambda df, cols: df[cols]
    ridx = lambda df, cols: df.reindex(columns=cols)
    ridxa = lambda df, cols: df.reindex_axis(cols, 1)

    isin = lambda df, dlst: ~df.columns.isin(dlst)
    in1d = lambda df, dlst: ~np.in1d(df.columns.values, dlst)
    comp = lambda df, dlst: [x not in dlst for x in df.columns.values.tolist()]
    brod = lambda df, dlst: (df.columns.values[:, None] != dlst).all(1)

    测试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    res1 = pd.DataFrame(
        index=pd.MultiIndex.from_product([
            'loc slc ridx ridxa'.split(),
            'setdiff1d difference columndrop setdifflst comprehension'.split(),
        ], names=['Select', 'Label']),
        columns=[10, 30, 100, 300, 1000],
        dtype=float
    )

    res2 = pd.DataFrame(
        index=pd.MultiIndex.from_product([
            'loc'.split(),
            'isin in1d comp brod'.split(),
        ], names=['Select', 'Label']),
        columns=[10, 30, 100, 300, 1000],
        dtype=float
    )

    res = res1.append(res2).sort_index()

    dres = pd.Series(index=res.columns, name='drop')

    for j in res.columns:
        dlst = list(range(j))
        cols = list(range(j // 2, j + j // 2))
        d = pd.DataFrame(1, range(10), cols)
        dres.at[j] = timeit('d.drop(dlst, 1, errors="ignore")', 'from __main__ import d, dlst', number=100)
        for s, l in res.index:
            stmt = '{}(d, {}(d, dlst))'.format(s, l)
            setp = 'from __main__ import d, dlst, {}, {}'.format(s, l)
            res.at[(s, l), j] = timeit(stmt, setp, number=100)

    rs = res / dres
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    rs

                              10        30        100       300        1000
    Select Label                                                          
    loc    brod           0.747373  0.861979  0.891144  1.284235   3.872157
           columndrop     1.193983  1.292843  1.396841  1.484429   1.335733
           comp           0.802036  0.732326  1.149397  3.473283  25.565922
           comprehension  1.463503  1.568395  1.866441  4.421639  26.552276
           difference     1.413010  1.460863  1.587594  1.568571   1.569735
           in1d           0.818502  0.844374  0.994093  1.042360   1.076255
           isin           1.008874  0.879706  1.021712  1.001119   0.964327
           setdiff1d      1.352828  1.274061  1.483380  1.459986   1.466575
           setdifflst     1.233332  1.444521  1.714199  1.797241   1.876425
    ridx   columndrop     0.903013  0.832814  0.949234  0.976366   0.982888
           comprehension  0.777445  0.827151  1.108028  3.473164  25.528879
           difference     1.086859  1.081396  1.293132  1.173044   1.237613
           setdiff1d      0.946009  0.873169  0.900185  0.908194   1.036124
           setdifflst     0.732964  0.823218  0.819748  0.990315   1.050910
    ridxa  columndrop     0.835254  0.774701  0.907105  0.908006   0.932754
           comprehension  0.697749  0.762556  1.215225  3.510226  25.041832
           difference     1.055099  1.010208  1.122005  1.119575   1.383065
           setdiff1d      0.760716  0.725386  0.849949  0.879425   0.946460
           setdifflst     0.710008  0.668108  0.778060  0.871766   0.939537
    slc    columndrop     1.268191  1.521264  2.646687  1.919423   1.981091
           comprehension  0.856893  0.870365  1.290730  3.564219  26.208937
           difference     1.470095  1.747211  2.886581  2.254690   2.050536
           setdiff1d      1.098427  1.133476  1.466029  2.045965   3.123452
           setdifflst     0.833700  0.846652  1.013061  1.110352   1.287831
    1
    2
    3
    4
    5
    6
    fig, axes = plt.subplots(2, 2, figsize=(8, 6), sharey=True)
    for i, (n, g) in enumerate([(n, g.xs(n)) for n, g in rs.groupby('Select')]):
        ax = axes[i // 2, i % 2]
        g.plot.bar(ax=ax, title=n)
        ax.legend_.remove()
    fig.tight_layout()

    这与运行df.drop(dlst, 1, errors='ignore')所需的时间有关。经过这么多努力,我们似乎只能适度地提高性能。

    enter image description here

    如果事实上,最好的解决方案在hack list(set(df.columns.values.tolist()).difference(dlst))上使用reindexreindex_axis。一个接近的第二个,而且仍然比drop要好得多的是np.setdiff1d

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    rs.idxmin().pipe(
        lambda x: pd.DataFrame(
            dict(idx=x.values, val=rs.lookup(x.values, x.index)),
            x.index
        )
    )

                          idx       val
    10     (ridx, setdifflst)  0.653431
    30    (ridxa, setdifflst)  0.746143
    100   (ridxa, setdifflst)  0.816207
    300    (ridx, setdifflst)  0.780157
    1000  (ridxa, setdifflst)  0.861622


    如果要从数据帧(df中删除单列(col_name),请尝试以下操作之一:

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

    1
    df.drop(col_name, axis=1, inplace=True)

    如果要从数据帧(df中删除列列表(col_lst = [col_name_1,col_name_2,...]),请尝试以下操作之一:

    1
    df.drop(col_lst, axis=1, inplace=True)

    1
    df.drop(columns=col_lst, inplace=True)

    点语法在javascript中有效,但在python中无效。

    • python:del df['column_name']
    • javascript:del df['column_name']del df.column_name


    尝试一下,我认为这是最简单的方法:

    drop((['A','B'],axis=1)


    另一种在熊猫数据帧中删除列的方法

    如果不希望就地删除,则可以通过使用DataFrame(...)函数将列指定为

    1
    2
    3
    my_dict = { 'name' : ['a','b','c','d'], 'age' : [10,20,25,22], 'designation' : ['CEO', 'VP', 'MD', 'CEO']}

    df = pd.DataFrame(my_dict)

    创建新的数据帧为

    1
    newdf = pd.DataFrame(df, columns=['name', 'age'])

    你会得到和del/drop一样好的结果