パンダ:名前がXで始まるすべての列を選択する最良の方法


104

私はデータフレームを持っています:

import pandas as pd
import numpy as np

df = pd.DataFrame({'foo.aa': [1, 2.1, np.nan, 4.7, 5.6, 6.8],
                   'foo.fighters': [0, 1, np.nan, 0, 0, 0],
                   'foo.bars': [0, 0, 0, 0, 0, 1],
                   'bar.baz': [5, 5, 6, 5, 5.6, 6.8],
                   'foo.fox': [2, 4, 1, 0, 0, 5],
                   'nas.foo': ['NA', 0, 1, 0, 0, 0],
                   'foo.manchu': ['NA', 0, 0, 0, 0, 0],})

で始まる列で値1を選択しますfoo.。それを行うためのより良い方法はありますか:

df2 = df[(df['foo.aa'] == 1)|
(df['foo.fighters'] == 1)|
(df['foo.bars'] == 1)|
(df['foo.fox'] == 1)|
(df['foo.manchu'] == 1)
]

次のようなものを書くのに似たもの:

df2= df[df.STARTS_WITH_FOO == 1]

答えは次のようなDataFrameを出力するはずです:

   bar.baz  foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu nas.foo
0      5.0     1.0         0             0        2         NA      NA
1      5.0     2.1         0             1        4          0       0
2      6.0     NaN         0           NaN        1          0       1
5      6.8     6.8         1             0        5          0       0

[4 rows x 7 columns]

回答:


151

リストを理解して列を作成するだけです。

In [28]:

filter_col = [col for col in df if col.startswith('foo')]
filter_col
Out[28]:
['foo.aa', 'foo.bars', 'foo.fighters', 'foo.fox', 'foo.manchu']
In [29]:

df[filter_col]
Out[29]:
   foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu
0     1.0         0             0        2         NA
1     2.1         0             1        4          0
2     NaN         0           NaN        1          0
3     4.7         0             0        0          0
4     5.6         0             0        0          0
5     6.8         1             0        5          0

別の方法は、列からシリーズを作成し、ベクトル化されたstrメソッドを使用することですstartswith

In [33]:

df[df.columns[pd.Series(df.columns).str.startswith('foo')]]
Out[33]:
   foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu
0     1.0         0             0        2         NA
1     2.1         0             1        4          0
2     NaN         0           NaN        1          0
3     4.7         0             0        0          0
4     5.6         0             0        0          0
5     6.8         1             0        5          0

目的を達成するには、次の行を追加して、==1基準を満たさない値をフィルタリングする必要があります。

In [36]:

df[df[df.columns[pd.Series(df.columns).str.startswith('foo')]]==1]
Out[36]:
   bar.baz  foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu nas.foo
0      NaN       1       NaN           NaN      NaN        NaN     NaN
1      NaN     NaN       NaN             1      NaN        NaN     NaN
2      NaN     NaN       NaN           NaN        1        NaN     NaN
3      NaN     NaN       NaN           NaN      NaN        NaN     NaN
4      NaN     NaN       NaN           NaN      NaN        NaN     NaN
5      NaN     NaN         1           NaN      NaN        NaN     NaN

編集する

あなたが複雑な答えが欲しいものを見た後にOKはこれです:

In [72]:

df.loc[df[df[df.columns[pd.Series(df.columns).str.startswith('foo')]] == 1].dropna(how='all', axis=0).index]
Out[72]:
   bar.baz  foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu nas.foo
0      5.0     1.0         0             0        2         NA      NA
1      5.0     2.1         0             1        4          0       0
2      6.0     NaN         0           NaN        1          0       1
5      6.8     6.8         1             0        5          0       0

66

パンダのインデックスが文字列操作をサポートするようになったので、おそらく 'foo'で始まる列を選択する最も簡単で最良の方法は次のとおりです。

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

または、列(または行)ラベルをでフィルタリングできますdf.filter()。で始まる名前に一致する正規表現を指定するにはfoo.

>>> df.filter(regex=r'^foo\.', axis=1)
   foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu
0     1.0         0             0        2         NA
1     2.1         0             1        4          0
2     NaN         0           NaN        1          0
3     4.7         0             0        0          0
4     5.6         0             0        0          0
5     6.8         1             0        5          0

必要な行(を含む1)と列のみを選択するには、を使用しlocfilter(またはその他の方法)を使用して列を選択し、を使用して行を選択しますany

>>> df.loc[(df == 1).any(axis=1), df.filter(regex=r'^foo\.', axis=1).columns]
   foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu
0     1.0         0             0        2         NA
1     2.1         0             1        4          0
2     NaN         0           NaN        1          0
5     6.8         1             0        5          0


1

@EdChumの回答に基づいて、次の解決策を試すことができます。

df[df.columns[pd.Series(df.columns).str.contains("foo")]]

これは、選択するすべての列がで始まっていない場合に非常に役立ちますfoo。このメソッドは、部分文字列を含むすべての列を選択し、列fooの名前の任意の場所に配置できます。

本質的に、私はに置き換え.startswith()ました.contains()


0

私の解決策。パフォーマンスが低下する可能性があります。

a = pd.concat(df[df[c] == 1] for c in df.columns if c.startswith('foo'))
a.sort_index()


   bar.baz  foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu nas.foo
0      5.0     1.0         0             0        2         NA      NA
1      5.0     2.1         0             1        4          0       0
2      6.0     NaN         0           NaN        1          0       1
5      6.8     6.8         1             0        5          0       0

0

目的のエントリを選択するための別のオプションは、以下を使用することmapです。

df.loc[(df == 1).any(axis=1), df.columns.map(lambda x: x.startswith('foo'))]

を含む行のすべての列が表示されます1

   foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu
0     1.0         0             0        2         NA
1     2.1         0             1        4          0
2     NaN         0           NaN        1          0
5     6.8         1             0        5          0

行選択をすることによって行われます

(df == 1).any(axis=1)

@ajcrの答えのように:

0     True
1     True
2     True
3    False
4    False
5     True
dtype: bool

つまり、行34はが含まれて1おらず、選択されません。

選択は、次のようなブールインデックスを使用して行われます

df.columns.map(lambda x: x.startswith('foo'))

上記の例では、これは

array([False,  True,  True,  True,  True,  True, False], dtype=bool)

カラムは始まらないのであれば、fooFalse返され、列はしたがって、選択されていません。

を含むすべての行を返すだけの場合1-希望する出力が示すように、あなたは単に行うことができます

df.loc[(df == 1).any(axis=1)]

戻る

   bar.baz  foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu nas.foo
0      5.0     1.0         0             0        2         NA      NA
1      5.0     2.1         0             1        4          0       0
2      6.0     NaN         0           NaN        1          0       1
5      6.8     6.8         1             0        5          0       0

0

ここで正規表現を試して、「foo」で始まる列を除外できます。

df.filter(regex='^foo*')

列に文字列fooが必要な場合

df.filter(regex='foo*')

適切でしょう。

次のステップでは、

df[df.filter(regex='^foo*').values==1]

「foo *」列の値の1つが1である行を除外します。


0

私の場合、プレフィックスのリストが必要でした

colsToScale=["production", "test", "development"]
dc[dc.columns[dc.columns.str.startswith(tuple(colsToScale))]]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.