web-dev-qa-db-fra.com

Comment sélectionner des colonnes de dataframe par regex

J'ai un dataframe en Python Pandas. La structure de la structure de données est la suivante: 

   a    b    c    d1   d2   d3 
   10   14   12   44  45    78

Je voudrais sélectionner les colonnes qui commencent par d. Existe-t-il un moyen simple de réaliser cela en python. 

38
Yan Song

Vous pouvez utiliser DataFrame.filter de cette façon:

import pandas as pd

df = pd.DataFrame(np.array([[2,4,4],[4,3,3],[5,9,1]]),columns=['d','t','didi'])
>>
   d  t  didi
0  2  4     4
1  4  3     3
2  5  9     1

df.filter(regex=("d.*"))

>>
   d  didi
0  2     4
1  4     3
2  5     1

L'idée est de sélectionner les colonnes par regex

78
farhawa

Utilisez select:

import pandas as pd

df = pd.DataFrame([[10, 14, 12, 44, 45, 78]], columns=['a', 'b', 'c', 'd1', 'd2', 'd3'])

df.select(lambda col: col.startswith('d'), axis=1)

Résultat:

   d1  d2  d3
0  44  45  78

C'est une solution intéressante si vous n'êtes pas à l'aise avec les expressions régulières.

16
gbrener

Vous pouvez utiliser une compréhension de liste pour parcourir tous les noms de colonne de votre DataFrame df et ne sélectionner que ceux commençant par 'd'.

df = pd.DataFrame({'a': {0: 10}, 'b': {0: 14}, 'c': {0: 12},
                   'd1': {0: 44}, 'd2': {0: 45}, 'd3': {0: 78}})

Utilisez la compréhension de liste pour parcourir les colonnes du cadre de données et renvoyer leurs noms (c ci-dessous est une variable locale représentant le nom de la colonne).

>>> [c for c in df]
['a', 'b', 'c', 'd1', 'd2', 'd3']

Ensuite, ne sélectionnez que ceux commençant par 'd'.

>>> [c for c in df if c[0] == 'd']  # As an alternative to c[0], use c.startswith(...)
['d1', 'd2', 'd3']

Enfin, transmettez cette liste de colonnes au DataFrame.

df[[c for c in df if c.startswith('d')]]
>>> df
   d1  d2  d3
0  44  45  78

=============================================== =========================

TIMINGS(ajouté en février 2018 par les commentaires de devinbost affirmant que cette méthode est lente ...)

Commençons par créer un cadre de données avec 30 000 colonnes:

n = 10000
cols = ['{0}_{1}'.format(letters, number) 
        for number in range(n) for letters in ('d', 't', 'didi')]
df = pd.DataFrame(np.random.randn(3, n * 3), columns=cols)
>>> df.shape
(3, 30000)

>>> %timeit df[[c for c in df if c[0] == 'd']]  # Simple list comprehension.
# 10 loops, best of 3: 16.4 ms per loop

>>> %timeit df[[c for c in df if c.startswith('d')]]  # More 'Pythonic'?
# 10 loops, best of 3: 29.2 ms per loop

>>> %timeit df.select(lambda col: col.startswith('d'), axis=1)  # Solution of gbrener.
# 10 loops, best of 3: 21.4 ms per loop

>>> %timeit df.filter(regex=("d.*"))  # Accepted solution.
# 10 loops, best of 3: 40 ms per loop
4
Alexander

Sur un plus grand ensemble de données, en particulier, une approche vectorisée est BEAUCOUP PLUS RAPIDE (de plus de deux ordres de grandeur) et BEAUCOUP plus lisible . Je fournis une capture d'écran comme preuve. (Remarque: à l'exception des dernières lignes que j'ai écrites en bas pour préciser mon point avec une approche vectorisée, l'autre code a été dérivé de la réponse de @Alexander.)

 enter image description here

Voici ce code pour référence:

import pandas as pd
import numpy as np
n = 10000
cols = ['{0}_{1}'.format(letters, number) 
        for number in range(n) for letters in ('d', 't', 'didi')]
df = pd.DataFrame(np.random.randn(30000, n * 3), columns=cols)

%timeit df[[c for c in df if c[0] == 'd']]

%timeit df[[c for c in df if c.startswith('d')]]

%timeit df.select(lambda col: col.startswith('d'), axis=1)

%timeit df.filter(regex=("d.*"))

%timeit df.filter(like='d')

%timeit df.filter(like='d', axis=1)

%timeit df.filter(regex=("d.*"), axis=1)

%timeit df.columns.map(lambda x: x.startswith("d"))

columnVals = df.columns.map(lambda x: x.startswith("d"))

%timeit df.filter(columnVals, axis=1)
2
devinbost

Vous pouvez aussi utiliser

df.filter(regex='^d')
0
prafi