首页 文章

使用del df.column_name从pandas DataFrame中删除列

提问于
浏览
874

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

del df['column_name']

这很有效 . 为什么我不能使用以下?

del df.column_name

由于您可以将列/系列作为 df.column_name 进行访问,因此我希望这可以正常工作 .

14 回答

  • 43

    在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)
    
  • 2

    使用:

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

    这将就地删除一个或多个列 . 请注意,在pandas v0.13中添加了 inplace=True 并且在这种情况下赢得't work on older versions. You' d必须返回结果:

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

    TL; DR

    寻找更有效的解决方案需要付出很多努力 . 在牺牲 df.drop(dlst, 1, errors='ignore') 的简单性的同时难以证明增加的复杂性

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

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

    我还将重点关注一次删除多个列的一般解决方案,并允许尝试删除不存在的列 .

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


    Setup
    考虑 pd.DataFrame df 和列表删除 dlst

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

    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
    

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

    结果应如下所示:

    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)
    Index(['A', 'B', 'C', 'D', 'E', 'F', 'G'], dtype='object')
    
    • np.setdiff1d(df.columns.values, dlst)
    array(['A', 'B', 'C', 'D', 'E', 'F', 'G'], dtype=object)
    
    • df.columns.drop(dlst, errors='ignore')
    Index(['A', 'B', 'C', 'D', 'E', 'F', 'G'], dtype='object')
    
    • list(set(df.columns.values.tolist()).difference(dlst))
    # does not preserve order
    ['E', 'D', 'B', 'F', 'G', 'A', 'C']
    
    • [x for x in df.columns.values.tolist() if x not in dlst]
    ['A', 'B', 'C', 'D', 'E', 'F', 'G']
    

    Columns from Labels
    为了比较选择过程,假设:

    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)

    所有评价为:

    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)

    Columns from Boolean
    为了比较

    bools = [x not in dlst for x in df.columns.values.tolist()]
    
    • df.loc[: bools]

    所有评价为:

    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
    

    Robust Timing

    功能

    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)
    

    Testing

    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
    

    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
    

    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') 所需的时间有关 . 看来,经过这么多努力,我们只能适度提高绩效 .

    事实上,最好的解决方案在hack list(set(df.columns.values.tolist()).difference(dlst)) 上使用 reindexreindex_axis . 紧随其后,仍然比 drop 好一点 np.setdiff1d .

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

    Another way of Deleting a Column in Pandas DataFrame

    如果您不是在寻找就地删除,那么您可以通过使用 DataFrame(...) 函数指定列来创建新的DataFrame

    my_dict = { 'name' : ['a','b','c','d'], 'age' : [10,20,25,22], 'designation' : ['CEO', 'VP', 'MD', 'CEO']}
    
    df = pd.DataFrame(my_dict)
    

    创建一个新的DataFrame作为

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

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

  • 11

    从版本0.16.1你可以做到

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

    按索引删除

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

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

    删除第一列:

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

    有一个可选参数 inplace ,因此可以在不创建副本的情况下修改原始数据 .

    弹出

    Column selection, addition, deletion

    删除列 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
    
  • 55

    始终使用 [] 表示法是一种好习惯 . 一个原因是属性表示法( 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
    
  • 489

    点语法适用于JavaScript,但不适用于Python .

    • Python: del df['column_name']

    • JavaScript: del df['column_name'] or del df.column_name

  • 1625

    由于Python中的语法限制,很难使 del df.column_name 工作变得简单 . del df[name] 被Python翻译为 df.__delitem__(name) .

  • 0

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

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

    要么

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

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

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

    要么

    df.drop(columns=col_lst, inplace=True)
    
  • 190

    在pandas中执行此操作的最佳方法是使用drop

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

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

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

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

    最后,要按列号而不是按列标签删除,请尝试删除,例如第1,第2和第4列:

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

    一个很好的补充是 drop columns only if they exist 的能力 . 这样,您可以覆盖更多用例,并且只会从传递给它的标签中删除现有列:

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

    df.drop(['col_name_1', 'col_name_2', ..., 'col_name_N'], inplace=True, axis=1, errors='ignore')
    
    • 这是pandas 0.16.1以后的新内容 . 文档是here .
  • 24

    大多数答案错过的实际问题是:

    为什么我不能使用deldf.column_name?

    首先,我们需要了解这个问题,这需要我们深入研究python magic methods .

    正如Wes在他的回答中指出 del df['column'] 映射到python魔法 df.__delitem__('column') 这是implemented in pandas to drop the column

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

    事实上,del几乎不应该被使用,因为它被称为不稳定的环境;谨慎使用!

    你可以说不应该使用或鼓励 del df['column_name'] ,因此甚至不应该考虑 del df.column_name .

    但是,从理论上讲, del df.column_name 可以用the magic method delattr实现在熊猫中工作 . 然而,这确实引入了某些问题,这些问题已经实施,但程度较轻 .

    示例问题

    如果我在名为“dtypes”或“columns”的数据框中定义列,该怎么办?

    然后假设我想删除这些列 .

    del df.dtypes 会使 __delattr__ 方法混淆,好像它应该删除"dtypes"属性或"dtypes"列 .

    这个问题背后的建筑问题

    • 数据框是列的集合吗?

    • 数据帧是行的集合吗?

    • 列是数据框的属性吗?

    熊猫的答案:

    • 是的,无论如何

    • 不,但是如果你想要它,你可以使用 .ix.loc.iloc 方法 .

    • 也许,你想读数据吗?然后 yes ,除非该属性的名称已被属于该数据帧的另一个属性所采用 . 你想修改数据吗?然后 no .

    TLDR;

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

    Protip:

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

    Python的引用适用于此处:

    删除列有多种方法 .

    应该有一个 - 最好只有一个 - 显而易见的方法 .

    列有时是属性,但有时不属于 .

    特殊情况不足以打破规则 .

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

    面对模棱两可,拒绝猜测的诱惑 .

  • 14

    熊猫0.21回答

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

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

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

相关问题