Usuń kolumny, których nazwa zawiera określony ciąg z pand DataFrame


106

Mam ramkę danych pandy z następującymi nazwami kolumn:

Wynik1, Test1, Wynik2, Test2, Wynik3, Test3, itd ...

Chcę usunąć wszystkie kolumny, których nazwa zawiera słowo „Test”. Numery takich kolumn nie są statyczne, ale zależą od poprzedniej funkcji.

Jak mogę to zrobić?

Odpowiedzi:


74
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

2
W OP nie określono, że przy usuwaniu nie będzie rozróżniana wielkość liter.
Phillip Cloud,

165

Oto jeden sposób, aby to zrobić:

df = df[df.columns.drop(list(df.filter(regex='Test')))]

47
Lub bezpośrednio na miejscu:df.drop(list(df.filter(regex = 'Test')), axis = 1, inplace = True)
Axel

7
To znacznie bardziej eleganckie rozwiązanie niż przyjęta odpowiedź. Rozbiłbym to nieco bardziej, aby pokazać dlaczego, głównie wyodrębniając, list(df.filter(regex='Test'))aby lepiej pokazać, co robi linia. Wybrałbym również df.filter(regex='Test').columnskonwersję ponad listy
Charles

2
Ta jest o wiele bardziej elegancka niż przyjęta odpowiedź.
deepelement

4
Naprawdę zastanawiam się, co oznaczają komentarze mówiące, że ta odpowiedź jest „elegancka”. Osobiście uważam to za dość zaciemnione, kiedy kod Pythona powinien być najpierw czytelny. Jest również dwukrotnie wolniejszy niż pierwsza odpowiedź. I używa regexsłowa kluczowego, gdy likewydaje się, że jest bardziej adekwatne.
Jacquot

2
W rzeczywistości nie jest to tak dobra odpowiedź, jak twierdzą ludzie. Problem filterpolega na tym, że zwraca kopię WSZYSTKICH danych jako kolumny , które chcesz usunąć. Jest to marnotrawstwo, jeśli przekazujesz ten wynik tylko do drop(co ponownie zwraca kopię) ... lepszym rozwiązaniem byłoby str.startswith(dodałem tutaj odpowiedź z tym).
cs95

42

Tańsze, szybsze i idiomatyczne: str.contains

W najnowszych wersjach pand możesz używać metod ciągów w indeksie i kolumnach. Tutaj,str.startswith wydaje się że dobrze pasuje.

Aby usunąć wszystkie kolumny zaczynające się od danego podciągu:

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

Aby dopasować bez rozróżniania wielkości liter, możesz użyć dopasowania opartego na wyrażeniach regularnych z str.contains z kotwicą SOL:

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

jeśli typy mieszane są możliwe, określ na=Falserównież.


15

Możesz odfiltrować wybrane kolumny za pomocą „filtru”

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

Teraz filtruj

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

Dostać..

   result1  result34
0   2.0     NaN
1   NaN     10.0

4
Najlepsza odpowiedź! Dzięki. Jak filtrujesz przeciwnie? not like='result'
przeciągnięcie 1

2
następnie zrób to: df = df.drop (df.filter (jak = 'wynik', oś = 1). kolumny, oś = 1)
Amir

14

Można to zrobić zgrabnie w jednej linii za pomocą:

df = df.drop(df.filter(regex='Test').columns, axis=1)

1
Podobnie (i szybciej):df.drop(df.filter(regex='Test').columns, axis=1, inplace=True)
Max Ghenis

9

Użyj DataFrame.selectmetody:

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

A operacja nie określiła, że ​​po „Test” musi następować liczba: chcę usunąć wszystkie kolumny, których nazwa zawiera słowo „Test” .
7stud

Założenie, że po teście następuje liczba, jest całkowicie uzasadnione. Przeczytaj ponownie pytanie.
Phillip Cloud,

2
teraz widzę:FutureWarning: 'select' is deprecated and will be removed in a future release. You can use .loc[labels.map(crit)] as a replacement
flutefreak7

Pamiętaj o tym import rewcześniej.
ijoseph

5

Ta metoda robi wszystko na swoim miejscu. Wiele innych odpowiedzi tworzy kopie i nie jest tak wydajnych:

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


2

Nie upuszczaj. Złap przeciwieństwo tego, czego chcesz.

df = df.filter(regex='^((?!badword).)*$').columns

1

najkrótsza droga to:

resdf = df.filter(like='Test',axis=1)

To było już objęte tą odpowiedzią .
Gino Mempin

1
Chociaż odpowiedź, do której link znajduje się w powyższym komentarzu, jest podobna, nie jest taka sama. W rzeczywistości jest prawie odwrotnie.
Makyen

0

Rozwiązanie w przypadku usuwania listy nazw kolumn zawierających wyrażenie regularne. Wolę to podejście, ponieważ często edytuję listę rozwijaną. Używa negatywnego wyrażenia regularnego filtru dla listy rozwijanej.

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)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.