[python] SQL에서와 같이 ‘in’과 ‘not in’을 사용하여 Pandas 데이터 프레임을 필터링하는 방법

SQL IN과 동등한 것을 어떻게 달성 할 수 NOT IN있습니까?

필요한 값이있는 목록이 있습니다. 시나리오는 다음과 같습니다.

df = pd.DataFrame({'countries':['US','UK','Germany','China']})
countries = ['UK','China']

# pseudo-code:
df[df['countries'] not in countries]

이 작업을 수행하는 현재 방법은 다음과 같습니다.

df = pd.DataFrame({'countries':['US','UK','Germany','China']})
countries = pd.DataFrame({'countries':['UK','China'], 'matched':True})

# IN
df.merge(countries,how='inner',on='countries')

# NOT IN
not_in = df.merge(countries,how='left',on='countries')
not_in = not_in[pd.isnull(not_in['matched'])]

그러나 이것은 끔찍한 kludge처럼 보인다. 누구든지 그것을 향상시킬 수 있습니까?



답변

사용할 수 있습니다 pd.Series.isin.

“IN”사용 : something.isin(somewhere)

또는 “NOT IN”의 경우 : ~something.isin(somewhere)

실례로 :

>>> df
  countries
0        US
1        UK
2   Germany
3     China
>>> countries
['UK', 'China']
>>> df.countries.isin(countries)
0    False
1     True
2    False
3     True
Name: countries, dtype: bool
>>> df[df.countries.isin(countries)]
  countries
1        UK
3     China
>>> df[~df.countries.isin(countries)]
  countries
0        US
2   Germany


답변

.query () 메소드 를 사용하는 대체 솔루션 :

In [5]: df.query("countries in @countries")
Out[5]:
  countries
1        UK
3     China

In [6]: df.query("countries not in @countries")
Out[6]:
  countries
0        US
2   Germany


답변

팬더 DataFrame에 대해 ‘in’과 ‘not in’을 구현하는 방법은 무엇입니까?

팬더 이벤트 두 가지 방법 : Series.isinDataFrame.isin각각 시리즈 및 DataFrames에 대해.


하나의 열을 기준으로 데이터 프레임 필터링 (시리즈에도 적용)

가장 일반적인 시나리오는 isin특정 열에 조건을 적용하여 DataFrame에서 행을 필터링하는 것입니다.

df = pd.DataFrame({'countries': ['US', 'UK', 'Germany', np.nan, 'China']})
df
  countries
0        US
1        UK
2   Germany
3     China

c1 = ['UK', 'China']             # list
c2 = {'Germany'}                 # set
c3 = pd.Series(['China', 'US'])  # Series
c4 = np.array(['US', 'UK'])      # array

Series.isin다양한 유형을 입력으로 받아들입니다. 다음은 원하는 것을 얻는 유효한 방법입니다.

df['countries'].isin(c1)

0    False
1     True
2    False
3    False
4     True
Name: countries, dtype: bool

# `in` operation
df[df['countries'].isin(c1)]

  countries
1        UK
4     China

# `not in` operation
df[~df['countries'].isin(c1)]

  countries
0        US
2   Germany
3       NaN

# Filter with `set` (tuples work too)
df[df['countries'].isin(c2)]

  countries
2   Germany

# Filter with another Series
df[df['countries'].isin(c3)]

  countries
0        US
4     China

# Filter with array
df[df['countries'].isin(c4)]

  countries
0        US
1        UK

많은 열에서 필터링

경우에 따라 여러 열에 대해 일부 검색어와 함께 ‘in’멤버십 확인을 적용하려고 할 수 있습니다.

df2 = pd.DataFrame({
    'A': ['x', 'y', 'z', 'q'], 'B': ['w', 'a', np.nan, 'x'], 'C': np.arange(4)})
df2

   A    B  C
0  x    w  0
1  y    a  1
2  z  NaN  2
3  q    x  3

c1 = ['x', 'w', 'p']

isin“A”및 “B”열 모두에 조건 을 적용하려면 DataFrame.isin다음을 사용하십시오 .

df2[['A', 'B']].isin(c1)

      A      B
0   True   True
1  False  False
2  False  False
3  False   True

이것으로부터 적어도 하나의 열이있는 행을 유지하기 위해Trueany 첫 번째 축을 따라 사용할 수 있습니다 .

df2[['A', 'B']].isin(c1).any(axis=1)

0     True
1    False
2    False
3     True
dtype: bool

df2[df2[['A', 'B']].isin(c1).any(axis=1)]

   A  B  C
0  x  w  0
3  q  x  3

모든 열을 검색하려면 열 선택 단계를 생략하고 수행하십시오.

df2.isin(c1).any(axis=1)

마찬가지로 모든 열이있는 행을 유지True 하려면 all이전과 동일한 방식으로 사용 하십시오.

df2[df2[['A', 'B']].isin(c1).all(axis=1)]

   A  B  C
0  x  w  0

주목할만한 언급 : numpy.isin,, query목록 이해 (문자열 데이터)

위에서 설명한 방법 외에도 numpy equivalent :을 사용할 수도 있습니다 numpy.isin.

# `in` operation
df[np.isin(df['countries'], c1)]

  countries
1        UK
4     China

# `not in` operation
df[np.isin(df['countries'], c1, invert=True)]

  countries
0        US
2   Germany
3       NaN

고려할 가치가있는 이유는 무엇입니까? NumPy 함수는 일반적으로 오버 헤드가 낮아 팬더에 비해 약간 빠릅니다. 이는 인덱스 정렬에 의존하지 않는 요소 별 연산이므로,이 방법이 pandas를 대체 할 수없는 상황은 거의 없습니다 isin.

문자열 작업은 벡터화하기 어렵 기 때문에 문자열 작업시 팬더 루틴은 일반적으로 반복됩니다. 여기서 목록 이해력이 더 빠를 것이라는 많은 증거가 있습니다. . 우리는 in지금 수표에 의지한다 .

c1_set = set(c1) # Using `in` with `sets` is a constant time operation... 
                 # This doesn't matter for pandas because the implementation differs.
# `in` operation
df[[x in c1_set for x in df['countries']]]

  countries
1        UK
4     China

# `not in` operation
df[[x not in c1_set for x in df['countries']]]

  countries
0        US
2   Germany
3       NaN

그러나 지정하기가 훨씬 더 어려우므로 수행중인 작업을 모르는 경우 사용하지 마십시오.

마지막 으로이 답변DataFrame.query 에서 다루는 내용 도 있습니다 . numexpr FTW!


답변

나는 일반적으로 다음과 같은 행에 대해 일반 필터링을 수행했습니다.

criterion = lambda row: row['countries'] not in countries
not_in = df[df.apply(criterion, axis=1)]


답변

BUSINESS_ID가 dfProfilesBusIds 인 BUSINESS_ID가있는 dfbc 행을 필터링하고 싶었습니다.

dfbc = dfbc[~dfbc['BUSINESS_ID'].isin(dfProfilesBusIds['BUSINESS_ID'])]


답변

답변에서 가능한 솔루션을 정리합니다.

IN의 경우 : df[df['A'].isin([3, 6])]

NOT IN의 경우 :

  1. df[-df["A"].isin([3, 6])]

  2. df[~df["A"].isin([3, 6])]

  3. df[df["A"].isin([3, 6]) == False]

  4. df[np.logical_not(df["A"].isin([3, 6]))]


답변

df = pd.DataFrame({'countries':['US','UK','Germany','China']})
countries = ['UK','China']

구현 :

df[df.countries.isin(countries)]

나머지 국가 에서 와 같이 구현하지 마십시오 .

df[df.countries.isin([x for x in np.unique(df.countries) if x not in countries])]