Löschen Sie Spalten, deren Name eine bestimmte Zeichenfolge aus pandas DataFrame enthält

105

Ich habe einen Pandas-Datenrahmen mit den folgenden Spaltennamen:

Ergebnis1, Test1, Ergebnis2, Test2, Ergebnis3, Test3 usw.

Ich möchte alle Spalten löschen, deren Name das Wort "Test" enthält. Die Anzahl solcher Spalten ist nicht statisch, sondern hängt von einer vorherigen Funktion ab.

Wie kann ich das machen?

Alexis Eggermont
quelle

Antworten:

72
import pandas as pd

import numpy as np

array=np.random.random((2,4))

df=pd.DataFrame(array, columns=('Test1', 'toto', 'test2', 'riri'))

print df

      Test1      toto     test2      riri
0  0.923249  0.572528  0.845464  0.144891
1  0.020438  0.332540  0.144455  0.741412

cols = [c for c in df.columns if c.lower()[:4] != 'test']

df=df[cols]

print df
       toto      riri
0  0.572528  0.144891
1  0.332540  0.741412
Nic
quelle
2
Das OP hat nicht angegeben, dass bei der Entfernung die Groß- und Kleinschreibung nicht berücksichtigt werden soll.
Phillip Cloud
160

Hier ist ein guter Weg dazu:

df = df[df.columns.drop(list(df.filter(regex='Test')))]
Bindiya12
quelle
47
Oder direkt an Ort und Stelle:df.drop(list(df.filter(regex = 'Test')), axis = 1, inplace = True)
Axel
7
Dies ist eine viel elegantere Lösung als die akzeptierte Antwort. Ich würde es ein bisschen mehr aufschlüsseln, um zu zeigen, warum, hauptsächlich extrahieren, list(df.filter(regex='Test'))um besser zu zeigen, was die Linie tut. Ich würde auch für sich entscheiden df.filter(regex='Test').columnsüber Listenkonvertierung
Charles
2
Dieser ist viel eleganter als die akzeptierte Antwort.
Deepelement
4
Ich frage mich wirklich, was die Kommentare zu dieser Antwort "elegant" bedeuten. Ich selbst finde es ziemlich verschleiert, wenn Python-Code zuerst lesbar sein sollte. Es ist auch doppelt so langsam wie die erste Antwort. Und es verwendet das regexSchlüsselwort, wenn das likeSchlüsselwort angemessener zu sein scheint.
Jacquot
2
Dies ist eigentlich keine so gute Antwort, wie die Leute behaupten. Das Problem dabei filterist, dass eine Kopie ALLER Daten als Spalten zurückgegeben wird , die Sie löschen möchten. Es ist verschwenderisch, wenn Sie dieses Ergebnis nur an übergeben drop(was wiederum eine Kopie zurückgibt) ... eine bessere Lösung wäre str.startswith(ich habe hier eine Antwort hinzugefügt ).
CS95
39

Billiger, schneller und idiomatischer: str.contains

In neueren Versionen von Pandas können Sie Zeichenfolgenmethoden für den Index und die Spalten verwenden. Hier str.startswithscheint eine gute Passform.

So entfernen Sie alle Spalten, die mit einem bestimmten Teilstring beginnen:

df.columns.str.startswith('Test')
# array([ True, False, False, False])

df.loc[:,~df.columns.str.startswith('Test')]

  toto test2 riri
0    x     x    x
1    x     x    x

Für die Übereinstimmung ohne Berücksichtigung der Groß- und Kleinschreibung können Sie die Regex-basierte Übereinstimmung str.containsmit einem SOL-Anker verwenden:

df.columns.str.contains('^test', case=False)
# array([ True, False,  True, False])

df.loc[:,~df.columns.str.contains('^test', case=False)] 

  toto riri
0    x    x
1    x    x

Wenn gemischte Typen möglich sind, geben Sie dies na=Falseebenfalls an.

cs95
quelle
15

Sie können die gewünschten Spalten mit 'filter' herausfiltern.

import pandas as pd
import numpy as np

data2 = [{'test2': 1, 'result1': 2}, {'test': 5, 'result34': 10, 'c': 20}]

df = pd.DataFrame(data2)

df

    c   result1     result34    test    test2
0   NaN     2.0     NaN     NaN     1.0
1   20.0    NaN     10.0    5.0     NaN

Jetzt filtern

df.filter(like='result',axis=1)

Bekommen..

   result1  result34
0   2.0     NaN
1   NaN     10.0
SAH
quelle
4
Beste Antwort! Vielen Dank. Wie filtert man gegenüber? not like='result'
StallingOne
2
dann mach das: df = df.drop (df.filter (like = 'result', axis = 1) .columns, axis = 1)
Amir
14

Dies kann ordentlich in einer Zeile erfolgen mit:

df = df.drop(df.filter(regex='Test').columns, axis=1)
Warren O'Neill
quelle
1
Ähnlich (und schneller):df.drop(df.filter(regex='Test').columns, axis=1, inplace=True)
Max Ghenis
9

Verwenden Sie die DataFrame.selectMethode:

In [38]: df = DataFrame({'Test1': randn(10), 'Test2': randn(10), 'awesome': randn(10)})

In [39]: df.select(lambda x: not re.search('Test\d+', x), axis=1)
Out[39]:
   awesome
0    1.215
1    1.247
2    0.142
3    0.169
4    0.137
5   -0.971
6    0.736
7    0.214
8    0.111
9   -0.214
Phillip Cloud
quelle
Und die Operation hat nicht angegeben, dass eine Zahl 'Test' folgen muss: Ich möchte alle Spalten löschen, deren Name das Wort "Test" enthält .
7stud
Die Annahme, dass eine Zahl auf Test folgt, ist durchaus vernünftig. Lesen Sie die Frage erneut.
Phillip Cloud
2
Jetzt sehen:FutureWarning: 'select' is deprecated and will be removed in a future release. You can use .loc[labels.map(crit)] as a replacement
Flutefreak7
Denken Sie daran, import revorher.
Ijoseph
5

Diese Methode erledigt alles an Ort und Stelle. Viele der anderen Antworten erstellen Kopien und sind nicht so effizient:

df.drop(df.columns[df.columns.str.contains('Test')], axis=1, inplace=True)

ba0101
quelle
2

Lass dich nicht fallen. Fangen Sie das Gegenteil von dem, was Sie wollen.

df = df.filter(regex='^((?!badword).)*$').columns
Roy Assis
quelle
1

Der kürzeste Weg ist:

resdf = df.filter(like='Test',axis=1)
ZacNt
quelle
Dies wurde bereits durch diese Antwort abgedeckt .
Gino Mempin
1
Die im obigen Kommentar verlinkte Antwort ist zwar ähnlich, aber nicht dieselbe. In der Tat ist es fast das Gegenteil.
Makyen
0

Lösung beim Löschen einer Liste von Spaltennamen, die Regex enthalten. Ich bevorzuge diesen Ansatz, weil ich die Dropdown-Liste häufig bearbeite. Verwendet einen negativen Filter-Regex für die Drop-Liste.

drop_column_names = ['A','B.+','C.*']
drop_columns_regex = '^(?!(?:'+'|'.join(drop_column_names)+')$)'
print('Dropping columns:',', '.join([c for c in df.columns if re.search(drop_columns_regex,c)]))
df = df.filter(regex=drop_columns_regex,axis=1)
BSalita
quelle