Supprimer la colonne de la base de données pandas en utilisant del DF.nom de la colonne

lors de la suppression d'une colonne dans un DataFrame j'utilise:

del df['column_name']

et ça marche très bien. Pourquoi je ne peux pas utiliser ce qui suit?

del df.column_name

comme vous pouvez accéder à la colonne/série comme df.column_name , Je m'attends à ce que cela fonctionne.

842
demandé sur Peter Mortensen 2012-11-16 10:26:40

13 réponses

il est difficile de faire fonctionner del df.column_name simplement à cause des limitations syntaxiques en Python. del df[name] est traduit en df.__delitem__(name) sous les couvertures par Python.

471
répondu Wes McKinney 2017-11-27 04:23:14

la meilleure façon de le faire dans pandas est d'utiliser drop :

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

1 est le axe nombre ( 0 pour les lignes et 1 pour les colonnes.)

pour supprimer la colonne sans avoir à réattribuer df vous pouvez faire:

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

enfin, de passer par la colonne numéro au lieu de par la colonne étiquette , essayez ceci pour supprimer, par exemple les 1ère, 2ème et 4ème colonnes:

df.drop(df.columns[[0, 1, 3]], axis=1)  # df.columns is zero-based pd.Index 
1569
répondu LondonRob 2017-11-17 21:50:03

utiliser:

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

supprimer une ou plusieurs colonnes en place. Notez que inplace=True a été ajouté dans les pandas v0.13 et ne fonctionne pas sur les anciennes versions. Vous devez affecter le résultat dans ce cas:

df = df.drop(columns, axis=1)
187
répondu Krishna Sankar 2018-05-23 19:44:08

Drop par l'indice

supprimer les première, deuxième et quatrième colonnes:

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

supprimer la première colonne:

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

il y a un paramètre optionnel inplace de sorte que l'original les données peuvent être modifiées sans créer de copie.

Sauté

sélection de colonne, Ajout, Suppression

supprimer la colonne column-name :

df.pop('column-name')

exemples:

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
83
répondu jezrael 2018-05-23 19:44:53

la question réelle posée, manquée par la plupart des réponses ici est:

Pourquoi Je ne peux pas utiliser del df.column_name ?

nous devons d'abord comprendre le problème, ce qui nous oblige à plonger dans Python magic methods .

comme Wes le souligne dans sa réponse del df['column'] cartes au python méthode magique df.__delitem__('column') qui est mis en œuvre dans pandas pour supprimer la colonne

Toutefois, comme indiqué dans le lien ci-dessus à propos de python méthodes magiques :

En fait, del ne devrait jamais être utilisée en raison de la précarité de la situation en vertu de laquelle il est appelé; utiliser avec prudence!

vous pourriez soutenir que del df['column_name'] devrait pas être utilisé ou encouragé, et ainsi del df.column_name ne devrait même pas être envisagée.

Cependant, en théorie, del df.column_name pourrait être mis en œuvre pour travailler dans les pandas en utilisant la méthode magique __delattr__ . Cela pose cependant certains problèmes, des problèmes que la mise en œuvre de del df['column_name'] pose déjà, mais à un degré moindre.

Exemple De Problème

et si je définissais une colonne dans une base de données appelée "dtypes" ou "columns".

Alors que je veux supprimer ces colonnes.

del df.dtypes rend la méthode __delattr__ confuse comme si elle devait supprimer l'attribut "dtypes" ou la colonne "dtypes".

questions D'architecture derrière ce problème

  1. est un dataframe a collection de colonnes ?
  2. Est-ce qu'un dataframe est une collection de lignes ?
  3. est une colonne attribut d'une base de données?

Pandas répond:

  1. Oui, dans tous les sens
  2. Non, mais si vous le voulez, vous pouvez utiliser les méthodes .ix , .loc ou .iloc .
  3. Peut-être, voulez-vous lire les données? Ensuite Oui , sauf si le nom de l'attribut est déjà pris par un autre attribut appartenant au dataframe. Voulez-vous modifier données? Puis Non .

TLDR;

Vous ne pouvez pas faire del df.column_name parce que les pandas a une assez sauvagement cultivé architecture qui doit être repensé pour ce genre de cognitive dissonance ne pas se produire à ses utilisateurs.

Protip:

N'utilisez pas df.column_name, Il est peut-être jolie, mais elle cause dissonance cognitive

Zen de Python citations qui s'inscrit ici:

Il y a plusieurs façons de supprimer une colonne.

il devrait y avoir une-et de préférence une seule-façon évidente de le faire.

Les colonnes

sont parfois des attributs, mais parfois non.

les cas spéciaux ne sont pas assez spéciaux pour enfreindre les règles.

est-ce que del df.dtypes supprime l'attribut dtypes ou la colonne dtypes?

face à l'ambiguïté, refusez la tentation de deviner.

55
répondu firelynx 2016-05-03 10:01:14

une belle addition est la possibilité de colonnes de chute seulement si elles existent . De cette façon, vous pouvez couvrir plus de cas d'utilisation, et il ne laissera tomber les colonnes existantes des étiquettes qui lui sont passées:

il suffit D'ajouter errors='ignore' , par exemple.:

df.drop(['col_name_1', 'col_name_2', ..., 'col_name_N'], inplace=True, axis=1, errors='ignore')
  • c'est nouveau à partir de pandas 0.16.1. La Documentation est ici .
43
répondu eiTan LaVi 2018-05-23 19:48:00

de la version 0.16.1 vous pouvez faire

df.drop(['column_name'], axis = 1, inplace = True, errors = 'ignore')
39
répondu sushmit 2016-10-21 21:20:09

c'est une bonne pratique d'utiliser toujours la notation [] . Une raison est que la notation d'attribut ( df.column_name ) ne fonctionne pas pour les indices numérotés:

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
24
répondu Andy Hayden 2018-05-23 19:43:02

dans pandas 0.16.1+ vous pouvez laisser tomber les colonnes seulement si elles existent selon la solution Postée par @eiTanLaVi. Avant cette version, vous pouvez obtenir le même résultat via une liste de compréhension conditionnelle:

df.drop([col for col in ['col_name_1','col_name_2',...,'col_name_N'] if col in df], 
        axis=1, inplace=True)
20
répondu Alexander 2016-11-22 15:15:42

Pandas de 0,21+ répondre

Pandas version 0.21 a modifié légèrement la méthode drop pour inclure à la fois les paramètres index et columns pour correspondre à la signature des méthodes rename et reindex .

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

personnellement, je préfère utiliser le paramètre axis pour désigner les colonnes ou l'index parce que c'est le paramètre mot-clé prédominant utilisé dans presque toutes les méthodes pandas. Mais, maintenant vous avez quelques choix supplémentaires dans la version 0.21.

12
répondu Ted Petrou 2018-09-20 18:48:41

TL; DR

beaucoup d'efforts pour trouver une solution légèrement plus efficace. Difficile de justifier la complexité ajoutée tout en sacrifiant la simplicité de df.drop(dlst, 1, errors='ignore')

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

préambule

Supprimer une colonne est sémantiquement la même chose que sélectionner les autres colonnes. Je vais vous montrer d'autres méthodes à envisager.

je me concentrerai aussi sur le solution générale consistant à supprimer plusieurs colonnes à la fois et à permettre la tentative de supprimer les colonnes absentes.

en utilisant ces solutions sont Générales et fonctionneront pour le cas simple aussi bien.


le programme d'Installation

Considérons le pd.DataFrame df et la liste pour supprimer 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']

le résultat doit ressembler à:

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

puisque j'égalise la suppression d'une colonne à la sélection des autres colonnes, je vais le briser en deux types:

    "1519760920 l'Étiquette de" sélection
  1. sélection booléenne

Sélection D'Une Étiquette

nous commençons par la fabrication de la liste/tableau d'étiquettes qui représentent les colonnes que nous voulons maintenir et sans les colonnes que nous voulons supprimer.

  1. df.columns.difference(dlst)

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

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

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

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

    ['A', 'B', 'C', 'D', 'E', 'F', 'G']
    

colonnes des étiquettes

Pour comparer le processus de sélection, supposons:

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

alors nous pouvons évaluer

  1. df.loc[:, cols]
  2. df[cols]
  3. df.reindex(columns=cols)
  4. df.reindex_axis(cols, 1)

que tous évaluent à:

   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

Tranche Booléenne

nous pouvons construire un tableau / liste de booléens pour trancher

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

colonnes de booléen

À des fins de comparaison

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

que tous évaluent à:

   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

Timing Robuste

fonctions

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)

Test

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()

ceci est relatif au temps qu'il faut pour exécuter df.drop(dlst, 1, errors='ignore') . Il semble qu'après tous ces efforts, nous n'améliorons que modestement nos performances.

enter image description here

si les meilleures solutions utiliser reindex ou reindex_axis sur le hack list(set(df.columns.values.tolist()).difference(dlst)) . Une seconde proche et encore très légèrement meilleure que drop est 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
11
répondu piRSquared 2017-09-20 14:28:55

la syntaxe des points fonctionne en JavaScript, mais pas en Python.

  • Python: del df['column_name']
  • JavaScript: del df['column_name'] ou del df.column_name
2
répondu Doctor 2018-07-04 10:14:49

une autre façon de supprimer une colonne dans la base de données Pandas

si vous n'êtes pas à la recherche de suppression en Place, alors vous pouvez créer une nouvelle datagramme en spécifiant les colonnes en utilisant DataFrame(...) fonction comme

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

df = pd.DataFrame(my_dict)

créer une nouvelle base de données comme

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

, Vous obtenez un résultat aussi bon que ce que vous obtenez avec del / déposer

0
répondu Daksh 2018-09-09 06:59:06