Frage Löschen Sie die Spalte aus Pandas DataFrame mit del df.column_name


Beim Löschen einer Spalte in einem DataFrame verwende ich:

del df['column_name']

Und das funktioniert großartig. Warum kann ich Folgendes nicht verwenden?

del df.column_name

Sie können auf die Spalte / Serie als zugreifen df.column_nameIch erwarte, dass das funktioniert.


814
2017-11-16 06:26


Ursprung


Antworten:


Es ist schwer zu machen del df.column_name funktionieren einfach als Ergebnis von syntaktischen Einschränkungen in Python. del df[name] wird übersetzt in df.__delitem__(name) unter der Decke von Python.


463
2017-11-21 03:12



Der beste Weg, dies in Pandas zu tun, ist zu verwenden drop:

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

woher 1 ist der Achse Nummer (0 für Reihen und 1 für Spalten.)

Um die Spalte zu löschen, ohne sie neu zuweisen zu müssen df du kannst tun:

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

Schließlich, um nach Spalte zu fallen Nummer statt nach Spalte EtiketteVersuchen Sie dies zu löschen, z.B. die 1., 2. und 4. Spalte:

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

1529
2017-08-09 11:12



Benutzen:

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

Dadurch werden eine oder mehrere Spalten an Ort und Stelle gelöscht. Beachten Sie, dass inplace=True wurde in pandas v0.13 hinzugefügt und funktioniert nicht mit älteren Versionen. Sie müssten das Ergebnis in diesem Fall zurückgeben:

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

178
2018-03-23 20:57



Drop-by-Index

Löschen Sie die erste, zweite und vierte Spalte:

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

Löschen Sie die erste Spalte:

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

Es gibt einen optionalen Parameter inplace so dass das Original Daten können geändert werden, ohne eine Kopie zu erstellen.

Geklappt

Spaltenauswahl, Hinzufügen, Löschen

Spalte löschen column-name:

df.pop('column-name')

Beispiele:

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

78
2017-07-15 13:37



Die eigentliche Frage gestellt, von den meisten Antworten hier fehlt ist:

Warum kann ich nicht verwenden? del df.column_name?

Zuerst müssen wir das Problem verstehen, in das wir eintauchen müssen Python magische Methoden.

Wie Wes in seiner Antwort betont del df['column'] Karten zum Python magische Methode  df.__delitem__('column') welches ist in Pandas implementiert, um die Spalte fallen zu lassen

Wie oben im Link erwähnt Python magische Methoden:

Eigentlich, del sollte fast nie wegen der prekären Umstände, unter denen es aufgerufen wird, verwendet werden; Benutze es mit Vorsicht!

Das könnte man bestreiten del df['column_name'] sollte nicht verwendet oder ermutigt werden, und dadurch del df.column_name sollte nicht einmal in Betracht gezogen werden.

In der Theorie, del df.column_name könnte implementiert werden, um in Pandas zu arbeiten das magische Methode __delattr__. Dies bringt jedoch einige Probleme mit sich, Probleme, die die del df['column_name'] Implementierung hat bereits, aber in geringerem Maße.

Beispiel Problem

Was passiert, wenn ich eine Spalte in einem Datenrahmen namens "dtypes" oder "columns" definiere.

Dann nehme ich an, dass ich diese Spalten löschen möchte.

del df.dtypes würde das machen __delattr__ Methode verwechselt, als ob es das "dtypes" Attribut oder die "dtypes" Spalte löschen sollte.

Architektonische Fragen hinter diesem Problem

  1. Ist ein Datenrahmen ein? Sammlung von Säulen?
  2. Ist ein Datenrahmen eine Sammlung von Reihen?
  3. Ist eine Spalte ein? Attribut eines Datenrahmens?

Pandas antwortet:

  1. Ja, in jeder Hinsicht
  2. Nein, aber wenn du es willst, kannst du das verwenden .ix, .loc oder .iloc Methoden.
  3. Vielleicht, willst du? lesen Daten? Dann Ja, es sei denn Der Name des Attributs wird bereits von einem anderen Attribut des Datenrahmens übernommen. Möchten Sie ändern Daten? Dann Nein.

TLDR;

Du kannst nicht tun del df.column_name weil Pandas eine ziemlich wild gewachsene Architektur hat, die für diese Art von neu überdacht werden muss kognitive Dissonanz nicht zu seinen Benutzern auftreten.

Protip:

Verwenden Sie nicht df.column_name, es kann schön sein, aber es verursacht kognitive Dissonanz

Zen of Python zitiert das passt hier rein:

Es gibt mehrere Möglichkeiten, eine Spalte zu löschen.

Es sollte eine - und vorzugsweise nur eine - offensichtliche Möglichkeit geben, dies zu tun.

Spalten sind manchmal Attribute, aber manchmal nicht.

Sonderfälle sind nicht speziell genug, um die Regeln zu brechen.

Tut del df.dtypes löschen Sie das Dtypes-Attribut oder die Dtypes-Spalte?

Angesichts der Mehrdeutigkeit, lehnen Sie die Versuchung ab zu erraten.


54
2018-05-03 09:48



Ab Version 0.16.1 können Sie tun

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

37
2018-04-30 18:57



Eine nette Ergänzung ist die Fähigkeit zu Spalten nur löschen, wenn sie existieren. Auf diese Weise können Sie mehr Anwendungsfälle abdecken und nur die vorhandenen Spalten aus den an sie übergebenen Labels löschen:

Einfach hinzufügen Fehler = 'ignorieren', beispielsweise.:

df.drop(['col_name_1', 'col_name_2', ..., 'col_name_N'], inplace=True, axis=1, errors='ignore')
  • Dies ist neu ab Pandas 0.16.1. Dokumentation ist Hier.

37
2018-01-03 12:29



Es ist eine gute Übung, immer die [] Notation. Ein Grund ist diese Attributschreibweise (df.column_name) funktioniert nicht für nummerierte Indizes:

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
2017-11-16 11:33



In Pandas 0.16.1+ können Sie Spalten nur dann löschen, wenn sie für die von @eiTanLaVi veröffentlichte Lösung existieren. Vor dieser Version können Sie dasselbe Ergebnis über ein bedingtes Listenverständnis erreichen:

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

20
2018-02-13 21:58



TL; DR

Viel Aufwand, um eine marginal effizientere Lösung zu finden. Schwierig, die zusätzliche Komplexität zu rechtfertigen, während die Einfachheit der df.drop(dlst, 1, errors='ignore')

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

Präambel
Das Löschen einer Spalte ist semantisch dasselbe wie das Auswählen der anderen Spalten. Ich werde ein paar zusätzliche Methoden zeigen.

Ich werde mich auch auf die allgemeine Lösung konzentrieren, mehrere Spalten gleichzeitig zu löschen und den Versuch zu ermöglichen, nicht vorhandene Spalten zu löschen.

Die Verwendung dieser Lösungen ist allgemein und wird auch für den einfachen Fall funktionieren.


Konfiguration
Bedenke die pd.DataFrame  df und Liste zum Löschen 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']

Das Ergebnis sollte wie folgt aussehen:

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

Da ich das Löschen einer Spalte mit dem Auswählen der anderen Spalten gleichstelle, werde ich sie in zwei Typen aufteilen:

  1. Etikettenauswahl
  2. Boolesche Auswahl

Etikettenauswahl

Wir beginnen mit der Herstellung der Liste / des Arrays von Labels, die die Spalten darstellen, die wir behalten möchten, und ohne die Spalten, die wir löschen wollen.

  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']
    

Spalten von Labels
Um den Auswahlprozess zu vergleichen, nehmen wir an:

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

Dann können wir bewerten

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

Welche alle bewerten zu:

   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

Boolesches Slice

Wir können ein Array / eine Liste von booleschen Werten für das Slicing konstruieren

  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)

Spalten von Boolean
Zum Vergleich

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

Welche alle bewerten zu:

   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

Robustes Timing 

Funktionen 

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)

Testen 

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

Dies ist relativ zu der Zeit, die zum Ausführen benötigt wird df.drop(dlst, 1, errors='ignore'). Es sieht so aus, als würden wir nach all dem Aufwand die Leistung nur moderat verbessern.

enter image description here

Wenn Tatsache die besten Lösungen verwenden reindex oder reindex_axis auf dem Hack list(set(df.columns.values.tolist()).difference(dlst)). Eine enge Sekunde und immer noch sehr viel besser als drop ist 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
2017-09-20 05:43



Pandas 0.21+ Antwort

Pandas Version 0.21 hat die Drop-Methode leicht geändert, um sowohl die index und columns Parameter zur Übereinstimmung mit der Signatur des rename und reindex Methoden.

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

Persönlich bevorzuge ich die Verwendung der axis Parameter, um Spalten oder Index zu bezeichnen, da es der vorherrschende Schlüsselwortparameter ist, der in fast allen Pandas-Methoden verwendet wird. Aber jetzt haben Sie einige Optionen in der Version 0.21.


10
2017-10-24 14:31