[python] 팬더 : 이름이 X로 시작하는 모든 열을 선택하는 가장 좋은 방법

DataFrame이 있습니다.

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]



답변

목록 이해를 수행하여 열을 만듭니다.

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

편집하다

원하는 것을 확인한 후 복잡한 대답은 다음과 같습니다.

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


답변

이제 pandas의 인덱스가 문자열 연산을 지원하므로 ‘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

필요한 행 (a 포함 1)과 열만 loc선택하려면을 사용하여 filter(또는 다른 방법)을 사용하여 열을 선택하고 다음을 사용 하여 행을 선택할 수 있습니다 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


답변

가장 간단한 방법은 열 이름에 직접 str을 사용하는 것입니다. pd.Series

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


답변

@EdChum의 답변에 따라 다음 솔루션을 시도 할 수 있습니다.

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

선택하려는 모든 열이로 시작하지 않는 경우 정말 유용 foo합니다. 이 메서드는 하위 문자열을 포함하는 모든 열을 선택 foo하며 열 이름의 어느 위치 에나 배치 할 수 있습니다.

본질적으로, 나는 대체 .startswith()와 함께 .contains().


답변

내 솔루션. 성능이 느려질 수 있습니다.

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


답변

원하는 항목을 선택하는 또 다른 옵션은 다음을 사용하는 것입니다 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

그 행을 의미 3 하고 4를 포함하지 않는1 및 선택되지 않습니다.

열 선택 다음과 같이 부울 색인을 사용하여 수행됩니다 :

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

위의 예에서 이것은

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

따라서 열이 다음으로 시작하지 않으면 foo ,False 리턴되고 열 때문에 선택되지 않습니다.

포함 된 모든 행을 반환하려면 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


답변

여기에서 정규식을 사용하여 “foo”로 시작하는 열을 필터링 할 수 있습니다.

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

열에 foo 문자열이 필요하면

df.filter(regex='foo*')

적절할 것입니다.

다음 단계에서는 다음을 사용할 수 있습니다.

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

‘foo *’열의 값 중 하나가 1 인 행을 필터링합니다.