web-dev-qa-db-ja.com

正規表現でデータフレームから列を選択する方法

python pandasにデータフレームがあります。データフレームの構造は次のとおりです。

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

Dで始まる列を選択したいと思います。 pythonでこれを達成する簡単な方法はありますか?.

48
Yan Song

DataFrame.filter この方法:

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

アイデアは、regexで列を選択することです

95
farhawa

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)

結果:

   d1  d2  d3
0  44  45  78

正規表現に慣れていない場合、これは素晴らしいソリューションです。

18
gbrener

リスト内包表記を使用して、DataFrame dfのすべての列名を反復処理し、「d」で始まる列のみを選択できます。

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

リスト内包表記を使用して、データフレーム内の列を反復処理し、それらの名前を返します(以下のcは列名を表すローカル変数です)。

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

次に、「d」で始まるもののみを選択します。

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

最後に、この列のリストをDataFrameに渡します。

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

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

[〜#〜] timings [〜#〜](この方法は遅いとdevinbostからのコメントごとに2018年2月に追加...)

最初に、3万列のデータフレームを作成します。

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
5
Alexander

特に大規模なデータセットでは、ベクトル化されたアプローチは実際には非常に速く(2桁以上)、はるかに読みやすいです。私は証拠としてスクリーンショットを提供しています。 (注:ベクトル化されたアプローチで私のポイントを明確にするために最後に書いた最後の数行を除いて、他のコードは答えから派生しました@Alexanderによって。)

enter image description here

参照用のコードは次のとおりです。

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)
3
devinbost

使用することもできます

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