Löschen mehrerer Spalten basierend auf Spaltennamen in Pandas

89

Ich habe einige Daten und wenn ich sie importiere, erhalte ich die folgenden nicht benötigten Spalten. Ich suche nach einer einfachen Möglichkeit, all diese zu löschen

   'Unnamed: 24', 'Unnamed: 25', 'Unnamed: 26', 'Unnamed: 27',
   'Unnamed: 28', 'Unnamed: 29', 'Unnamed: 30', 'Unnamed: 31',
   'Unnamed: 32', 'Unnamed: 33', 'Unnamed: 34', 'Unnamed: 35',
   'Unnamed: 36', 'Unnamed: 37', 'Unnamed: 38', 'Unnamed: 39',
   'Unnamed: 40', 'Unnamed: 41', 'Unnamed: 42', 'Unnamed: 43',
   'Unnamed: 44', 'Unnamed: 45', 'Unnamed: 46', 'Unnamed: 47',
   'Unnamed: 48', 'Unnamed: 49', 'Unnamed: 50', 'Unnamed: 51',
   'Unnamed: 52', 'Unnamed: 53', 'Unnamed: 54', 'Unnamed: 55',
   'Unnamed: 56', 'Unnamed: 57', 'Unnamed: 58', 'Unnamed: 59',
   'Unnamed: 60'

Sie werden durch 0-Indizierung indiziert, also habe ich so etwas versucht

    df.drop(df.columns[[22, 23, 24, 25, 
    26, 27, 28, 29, 30, 31, 32 ,55]], axis=1, inplace=True)

Das ist aber nicht sehr effizient. Ich habe versucht, einige für Loops zu schreiben, aber das kam mir als schlechtes Pandas-Verhalten vor. Daher stelle ich hier die Frage.

Ich habe einige ähnliche Beispiele gesehen ( Pandas mit mehreren Spalten löschen ), aber dies beantwortet meine Frage nicht.

Peadar Coyle
quelle
2
Was meinst du mit effizient? Läuft es zu langsam? Wenn Ihr Problem darin besteht, dass Sie nicht die Indizes aller zu löschenden Spalten abrufen möchten, beachten Sie bitte, dass Sie nur df.dropeine Liste der Spaltennamen angeben können:df.drop(['Unnamed: 24', 'Unnamed: 25', ...], axis=1)
Carsten
Wäre es nicht einfacher, nur die interessierenden Spalten zu unterteilen: dh df = df[cols_of_interest]Sie könnten den df nach Spalten df.drop(df.ix[:,'Unnamed: 24':'Unnamed: 60'].head(0).columns, axis=1)
aufteilen
2
Ich meinte ineffizient in Bezug auf das Schreiben oder "schlechten Code-Geruch"
Peadar Coyle
1
Es könnte erwähnenswert sein, dass es in den meisten Fällen einfacher ist, die gewünschten Spalten beizubehalten und diejenigen zu löschen, die Sie nicht haben: df = df ['col_list']
sparrow

Antworten:

61

Ich weiß nicht, was Sie unter ineffizient verstehen, aber wenn Sie in Bezug auf die Eingabe meinen, könnte es einfacher sein, einfach die interessierenden Spalten auszuwählen und dem df wieder zuzuweisen:

df = df[cols_of_interest]

Wo cols_of_interestist eine Liste der Spalten, die Sie interessieren.

Oder Sie können die Spalten in Scheiben schneiden und diese übergeben an drop:

df.drop(df.ix[:,'Unnamed: 24':'Unnamed: 60'].head(0).columns, axis=1)

Der Aufruf, headnur 0 Zeilen auszuwählen, da wir nur an den Spaltennamen und nicht an den Daten interessiert sind

aktualisieren

Eine andere Methode: Es wäre einfacher, die Boolesche Maske von zu verwenden str.containsund sie zu invertieren, um die Spalten zu maskieren:

In [2]:
df = pd.DataFrame(columns=['a','Unnamed: 1', 'Unnamed: 1','foo'])
df

Out[2]:
Empty DataFrame
Columns: [a, Unnamed: 1, Unnamed: 1, foo]
Index: []

In [4]:
~df.columns.str.contains('Unnamed:')

Out[4]:
array([ True, False, False,  True], dtype=bool)

In [5]:
df[df.columns[~df.columns.str.contains('Unnamed:')]]

Out[5]:
Empty DataFrame
Columns: [a, foo]
Index: []
EdChum
quelle
Ich erhalte Fehler, wenn ich versuche, entweder ~ df.columns ... (TypeError: falscher Operandentyp für unary ~: 'str') oder df.columns.str.contains ... (AttributeError: 'Index'-Objekt hat kein Attribut 'str'). Irgendwelche Ideen, warum das so sein könnte?
Dai
@EdChum kann ich df = df [cols_of_interest] erstellen , wobei cols_of_interest jedes Mal , wenn eine for-Schleife wiederholt wird, einen Spaltennamen hinzufügt?
@ Victor nein, wenn du das tust, überschreibst du deine dfmit deiner neuen Kolumne, solltest du appendvielleicht, aber ich verstehe deine Frage nicht wirklich, du solltest eine echte Frage auf SO posten, anstatt als Kommentar zu fragen, da es eine schlechte Form auf SO ist
EdChum
@ EdChum du hast absolut recht. Ich habe die Frage erstellt und versuche sie zu lösen, indem ich verschiedene Teile von SO durchsuche. Hier ist der Link ! Jeder Beitrag hilft stackoverflow.com/questions/48923915/…
206

Der mit Abstand einfachste Ansatz ist:

yourdf.drop(['columnheading1', 'columnheading2'], axis=1, inplace=True)
Philipp Schwarz
quelle
Ich habe dieses Format in einigen meiner Codes verwendet und erhalte eine SettingWithCopyWarningWarnung?
KillerSnail
2
@KillerSnail, es ist sicher zu ignorieren. Um Fehler zu vermeiden, versuchen Sie: df = df.drop (['colheading1', 'colheading2'], axis = 1)
Philipp Schwarz
4
Der Begriff axiserklärt: stackoverflow.com/questions/22149584/… . Im Wesentlichen axis=0wird gesagt, "spaltenweise" und axis=1"zeilenweise" zu sein.
Rohmer
3
Und inplace=Truebedeutet, dass das DataFramean Ort und Stelle geändert wird.
Rohmer
1
@ Killernail, wenn Sie die Warnung nicht wollen, tun Sieyourdf = yourdf.drop(['columnheading1', 'columnheading2'], axis=1)
happy_sisyphus
39

Mein persönlicher Favorit und einfacher als die Antworten, die ich hier gesehen habe (für mehrere Spalten):

df.drop(df.columns[22:56], axis=1, inplace=True)

Oder erstellen Sie eine Liste für mehrere Spalten.

col = list(df.columns)[22:56]
df.drop(col, axis=1, inplace=1)
sheldonzy
quelle
7
Dies sollte die Antwort sein. Am saubersten, am einfachsten zu lesen, mit einfacher nativer Pandas-Indizierungssyntax.
Brent Faust
2
Diese Antwort sollte das grüne Häkchen haben, nicht die anderen.
Siavosh Mahboubian
1
Kleine Korrektur (es sei denn, ich irre mich): Der zweite Codeblock sollte 'inplace = True' anstelle von 'inplace = 1' haben.
Thredolsen
20

Dies ist wahrscheinlich ein guter Weg, um das zu tun, was Sie wollen. Es werden alle Spalten gelöscht, deren Kopfzeile "Unbenannt" enthält.

for col in df.columns:
    if 'Unnamed' in col:
        del df[col]
knightofni
quelle
Dies for col in df.columns:kann vereinfacht werden for col in df:, auch das OP hat nicht angegeben, was das Benennungsschema für die anderen Spalten ist, sie könnten alle 'Unbenannt' enthalten, auch dies ist ineffizient, da es die Spalten
einzeln
Es ist sicherlich nicht effizient, aber solange wir nicht an riesigen Datenrahmen arbeiten, wird es keine signifikanten Auswirkungen haben. Der Pluspunkt dieser Methode ist, dass sie einfach zu merken und schnell zu codieren ist. Das Erstellen einer Liste der Spalten, die Sie behalten möchten, kann sehr schmerzhaft sein.
Knightofni
Ich denke, dass dies bei großen df wahrscheinlich am performantesten ist, da Sie keine lokale Kopie mitinplace = True
Matt
13

Sie können dies in einer Zeile und auf einmal tun:

df.drop([col for col in df.columns if "Unnamed" in col], axis=1, inplace=True)

Dies beinhaltet weniger Bewegen / Kopieren des Objekts als die obigen Lösungen.

Peter
quelle
11

Ich bin mir nicht sicher, ob diese Lösung bereits irgendwo erwähnt wurde, aber eine Möglichkeit ist dies pandas.Index.difference.

>>> df = pd.DataFrame(columns=['A','B','C','D'])
>>> df
Empty DataFrame
Columns: [A, B, C, D]
Index: []
>>> to_remove = ['A','C']
>>> df = df[df.columns.difference(to_remove)]
>>> df
Empty DataFrame
Columns: [B, D]
Index: []
px06
quelle
3

Sie können die Spaltennamen einfach als Liste übergeben, indem Sie die Achse als 0 oder 1 angeben

  • Achse = 1: Entlang der Zeilen
  • Achse = 0: Entlang der Spalten
  • Standardmäßig ist Achse = 0

    data.drop(["Colname1","Colname2","Colname3","Colname4"],axis=1)

Maddu Swaroop
quelle
1

Das Folgende hat bei mir funktioniert:

for col in df:
    if 'Unnamed' in col:
        #del df[col]
        print col
        try:
            df.drop(col, axis=1, inplace=True)
        except Exception:
            pass
Shivgan
quelle
1

Simpel und einfach. Entfernen Sie alle Spalten nach dem 22 ..

df.drop(columns=df.columns[22:]) # love it
Niedson
quelle
0

df = df[[col for col in df.columns if not ('Unnamed' in col)]]

Sarah
quelle
1
Dies ist ähnlich wie bei Peter, außer dass unerwünschte Spalten herausgefiltert anstatt gelöscht werden.
Sarah