it-swarm.com.de

Spalte aus Pandas DataFrame löschen

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

del df['column_name']

Und das funktioniert super. Warum kann ich Folgendes nicht verwenden?

del df.column_name

Da Sie auf die Spalte/Serie als df.column_name zugreifen können, erwarte ich, dass dies funktioniert.

914
John

Es ist schwierig, del df.column_name einfach als Ergebnis syntaktischer Einschränkungen in Python funktionieren zu lassen. del df[name] wird von Python unter den Covers in df.__delitem__(name) übersetzt.

512
Wes McKinney

Der beste Weg, dies in Pandas zu tun, ist die Verwendung von drop :

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

dabei ist 1 die Nummer der axis (0 für Zeilen und 1 für Spalten).

Um die Spalte zu löschen, ohne df neu zuordnen zu müssen, können Sie Folgendes tun:

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

Um schließlich nach Spalte number anstelle von Spalte label zu löschen, versuchen Sie dies zu löschen, z. die 1., 2. und 4. Spalte:

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

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 in Pandas v0.13 hinzugefügt wurde und mit älteren Versionen nicht funktioniert. In diesem Fall müssten Sie das Ergebnis wieder zuweisen:

df = df.drop(columns, axis=1)
194
Krishna Sankar

Nach Index wechseln

Erste, zweite und vierte Spalte löschen:

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

Erste Spalte löschen:

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

Es gibt einen optionalen Parameter inplace, damit das Originaldata geändert werden kann, ohne eine Kopie zu erstellen.

Geknallt

Spaltenauswahl, Hinzufügen, Löschen

Spalte column-name löschen:

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
90
jezrael

Die eigentliche Frage, die hier von den meisten Antworten übersehen wird, lautet:

Warum kann ich del df.column_name Nicht verwenden?

Zuerst müssen wir das Problem verstehen, das es erfordert, dass wir uns mit python magic methods beschäftigen.

Wie Wes in seiner Antwort ausführt, entspricht del df['column'] Der python magische Methodedf.__delitem__('column')) implementiert in pandas um die Spalte zu löschen

Wie im obigen Link zu Python-Magiemethoden ausgeführt:

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

Sie könnten argumentieren, dass del df['column_name'] Nicht verwendet oder empfohlen werden sollte und daher del df.column_name Nicht einmal in Betracht gezogen werden sollte.

Theoretisch könnte jedoch del df.column_name Implementiert werden, um in pandas mit der magic method __delattr__ Zu arbeiten = . Dies führt jedoch zu bestimmten Problemen, die die del df['column_name'] - Implementierung bereits hat, jedoch in geringerem Maße.

Beispiel Problem

Was ist, wenn ich eine Spalte in einem Datenrahmen mit dem Namen "dtypes" oder "columns" definiere?.

Dann gehe ich davon aus, dass ich diese Spalten löschen möchte.

del df.dtypes Würde die Methode __delattr__ Verwirren, als würde sie das Attribut "dtypes" oder die Spalte "dtypes" löschen.

Architekturfragen hinter diesem Problem

  1. Ist ein Datenframe eine Sammlung von Spalten?
  2. Ist ein Datenframe eine Sammlung von Zeilen?
  3. Ist eine Spalte ein Attribut ​​eines Datenrahmens?

Pandas Antworten:

  1. Ja, in jeder Hinsicht
  2. Nein, aber wenn Sie möchten, können Sie die Methoden .ix, .loc Oder .iloc Verwenden.
  3. Möchtest du vielleicht read data? Dann yes , es sei denn der Name des Attributs wird bereits von einem anderen zum Datenrahmen gehörenden Attribut übernommen. Möchten Sie ändern Daten? Dann nein .

TLDR;

Sie können del df.column_name Nicht machen, weil pandas) eine ziemlich wild gewachsene Architektur hat, die überdacht werden muss, damit diese Art von kognitiver Dissonanz nicht auftritt seine Benutzer.

Protip:

Verwenden Sie nicht df.column_name. Es mag hübsch sein, aber es verursacht kognitive Dissonanz

Zen von Python Anführungszeichen, die hier passen:

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

Es sollte einen - und am besten nur einen - offensichtlichen Weg geben, dies zu tun.

Spalten sind manchmal Attribute, aber manchmal nicht.

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

Löscht del df.dtypes Das Attribut dtypes oder die Spalte dtypes?

Lehnen Sie bei Zweideutigkeiten die Versuchung ab, zu raten.

63
firelynx

Ein netter Zusatz ist die Möglichkeit, nur Spalten löschen, wenn sie existieren. Auf diese Weise können Sie mehr Anwendungsfälle abdecken. Dabei werden nur die vorhandenen Spalten von den übergebenen Labels gelöscht:

Fügen Sie einfach errors = 'ignore' hinzu, zum Beispiel:

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

ab Version 0.16.1 ist das möglich 

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

Es empfiehlt sich, immer die []-Notation zu verwenden. Ein Grund ist, dass die Attributnotation (df.column_name) für nummerierte Indizes nicht funktioniert:

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
26
Andy Hayden

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

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

Pandas 0.21+ Antwort

Pandas Version 0.21 hat die Methode drop geringfügig geändert, um sowohl die Parameter index als auch columns mit der Signatur der Methoden rename und reindex zu verbinden. 

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

Ich persönlich bevorzuge die Verwendung des Parameters axis zur Bezeichnung von Spalten oder Indizes, da dies der vorherrschende Schlüsselwortparameter ist, der in fast allen Pandas-Methoden verwendet wird. Jetzt haben Sie in Version 0.21 jedoch einige Optionen hinzugefügt.

15
Ted Petrou

TL; DR

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

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

Präambel
Das Löschen einer Spalte entspricht semantisch dem Auswählen der anderen Spalten. Ich werde ein paar zusätzliche Methoden zeigen, die zu berücksichtigen sind.

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 funktioniert auch für den einfachen Fall.


Setup
Betrachten Sie den pd.DataFramedf und die Liste, um dlst zu löschen.

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 so 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 gleichsetze, werde ich sie in zwei Typen unterteilen:

  1. Etikettenauswahl
  2. Boolesche Auswahl

Etikettenauswahl

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

  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 aus 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 auswerten

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

Was alle auswerten, um:

   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

Boolesche Scheibe

Wir können ein Array/eine Liste von Booleschen Werten zum Schneiden erstellen

  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 aus Boolean
Zum Vergleich

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

Was alle auswerten, um:

   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 benötigt wird, um df.drop(dlst, 1, errors='ignore') auszuführen. Es scheint, dass wir nach all diesen Anstrengungen die Leistung nur bescheiden verbessern.

enter image description here

In der Tat verwenden die besten Lösungen reindex oder reindex_axis Auf dem Hack list(set(df.columns.values.tolist()).difference(dlst)). Eine knappe Sekunde und immer noch etwas 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
13
piRSquared

Wenn Sie eine einzelne Spalte (col_name) aus einem Datenrahmen (df) löschen möchten, versuchen Sie eine der folgenden Methoden:

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

ODER 

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

Wenn Sie eine Liste von Spalten (col_lst = [col_name_1,col_name_2,...]) aus einem Datenrahmen (df) löschen möchten, führen Sie einen der folgenden Schritte aus:

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

ODER 

df.drop(columns=col_lst, inplace=True)
7
Stephanie

Die Punktsyntax funktioniert in JavaScript, jedoch nicht in Python.

  • Python: del df['column_name']
  • JavaScript: del df['column_name'] oder del df.column_name
2
Doctor

versuche dies, ich denke das ist der einfachste Weg:

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

1
Aymen Alsaadi

Spalte (n) aus mehreren Datenrahmen löschen

Wenn Sie hier nach Informationen zum Löschen einer Spalte (mit demselben Namen) aus einer Liste von DataFrames gesucht haben, gibt es verschiedene Möglichkeiten.

Eine Methode besteht darin, die Liste zu durchlaufen und jeden DataFrame direkt zu ändern:

# In-place assignment
for df in df_list:
    df.drop('colname', axis=1, inplace=True)

Oder,

for df in df_list: df.pop('colname')

Alternativ können Sie die Spalte löschen (nicht vorhanden) und das Ergebnis wieder dieser Listenposition zuweisen.

# Reassigning a copy back to the list
for i, df in enumerate(df_list):
    df_list[i] = df.drop('colname', axis=1, inplace=True)

Reproduzierbares Codebeispiel

df1 = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
df2 = pd.DataFrame({'A': [4, 5, 7], 'C': ['a', 'b', 'c']})

df1
   A  B
0  1  4
1  2  5
2  3  6

df2
   A  C
0  4  a
1  5  b
2  7  c

df_list = [df1, df2]
# Drop column "A"
for df in df_list:
    df.drop('A', axis=1, inplace=True)

df1
   B
0  4
1  5
2  6

df2
   C
0  a
1  b
2  c

Warum funktioniert for df in df_list: df = df.drop('colname', axis=1)d. H. Neuzuweisung innerhalb der Schleife) nicht?

Wie in anderen Antworten erwähnt, gibt df.drop standardmäßig eine Kopie zurück. Die Kopie wird zurückgegeben und dem Variablendfzugewiesen, ohne dass das Original geändert werden muss. Sie müssten entweder dfdirekt mit dem Argument inplace=True ändern oder die Kopie explizit diesem Listenelement zuweisen.

Hinweis
Es ist wichtig, den Unterschied zwischen Variablen und Objekten zu verstehen. Variablen enthalten Verweise auf Objekte. Variablen können neu zugewiesen werden, um auf verschiedene Objekte zu verweisen. Dies hat nichts mit dem Ändern des Objekts selbst zu tun. Für eine gute Einführung in dieses Thema empfehle ich _ (dieser Artikel von Ned Batchelder.

1
cs95

Eine andere Methode zum Löschen einer Spalte in Pandas DataFrame

wenn Sie nicht direkt nach dem Löschen suchen, können Sie einen neuen DataFrame erstellen, indem Sie die Spalten mit DataFrame(...) als angeben

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

df = pd.DataFrame(my_dict)

Erstellen Sie einen neuen DataFrame als

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

Sie erhalten ein Ergebnis so gut wie das, was Sie mit del/drop erhalten

0
Daksh