Pandas veri çerçevesini SQL'de olduğu gibi 'in' ve 'not in' kullanarak nasıl filtreleyebilirim?


432

Nasıl SQL en karşılıkları elde edebilirsiniz INve NOT IN?

Gerekli değerleri içeren bir listem var. İşte senaryo:

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

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

Şu anki bunu yapmam şu şekildedir:

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'])]

Ama bu korkunç bir çamur gibi görünüyor. Birisi bunu geliştirebilir mi?


1
Bence çözümünüz en iyi çözüm. Sizinki, birden çok sütunun IN, NOT_IN değerini kapsayabilir.
Bruce Jung

Tek veya birden çok sütunu test etmek istiyor musunuz?
smci

1
İlgili (performans / pandalar iç): Sete karşı dizi ile pandalar pd.Series.isin performansı
jpp

Yanıtlar:


820

Kullanabilirsiniz pd.Series.isin.

"IN" için şunları kullanın: something.isin(somewhere)

Veya "IN IN" için: ~something.isin(somewhere)

Çalışan bir örnek olarak:

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

1
Sadece bir FYI, @LondonRob'un DataFrame'i vardı ve sizinki bir Seri. DataFrame'ler .13'te isineklendi.
TomAugspurger

Pandalar 0.12.0 ile bunu yapmak için herhangi bir öneriniz var mı? Güncel olarak yayınlanan sürüm. (Belki sadece 0.13 beklemeliyim ?!)
LondonRob

Aslında 1 boyutlu dizilerle uğraşıyorsanız (örnekte olduğu gibi), ilk satırda @DSM kullanılan gibi bir DataFrame yerine bir Seri kullanırsınız:df = pd.Series({'countries':['US','UK','Germany','China']})
TomAugspurger

2
@ TomAugspurger: her zamanki gibi, muhtemelen bir şey eksik. df, hem benim hem de onun bir DataFrame. countriesbir listedir. df[~df.countries.isin(countries)]a DataFramedeğil, üretir Seriesve 0.11.0.dev-14a04dd'de bile geri çalışıyor gibi görünüyor.
DSM

7
countriesDeğişkeni tekrar kullanmaya devam ettiğiniz için bu cevap kafa karıştırıcıdır . OP bunu yapar ve bu kalıtsaldır, ancak daha önce kötü bir şey yapıldığını şimdi kötü yapmayı haklı çıkarmaz.
ifly6

63

.Query () yöntemini kullanan alternatif çözüm :

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

10
@LondonRob queryartık deneysel değil.
Paul Rougieux

38

Panda DataFrame için 'içeri' ve 'içeri' nasıl uygulanır?

Pandalar teklifler iki yöntem: Series.isinve DataFrame.isinsırasıyla Serisi ve DataFrames için.


Bir Sütuna Dayalı DataFrame'i Filtrele (Seri için de geçerlidir)

En yaygın senaryo, isinDataFrame'deki satırları filtrelemek için belirli bir sütuna bir koşul uygulamaktır .

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çeşitli türleri girdi olarak kabul eder. Aşağıdakilerin hepsi, istediğinizi elde etmenin geçerli yollarıdır:

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

BİRÇOK Sütun Üzerine Filtre

Bazen, birden fazla sütun üzerinde bazı arama terimleriyle 'giriş' üyelik kontrolü uygulamak istersiniz,

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']

isinKoşulu "A" ve "B" sütunlarına uygulamak için şunu kullanın DataFrame.isin:

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

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

Bundan, en az bir sütunun olduğu satırları tutmakTrueany için ilk eksen boyunca kullanabiliriz :

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

Her sütunu aramak istiyorsanız, sütun seçimi adımını atlayıp

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

Benzer şekilde, TÜM sütunların olduğu satırları tutmakTrueall için öncekiyle aynı şekilde kullanın .

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

   A  B  C
0  x  w  0

Önemli Mentions: numpy.isin,, queryliste anlama (dize verileri)

Yöntemlere ilave edilmesi yukarıda açıklanan, aynı zamanda numpy eşdeğer kullanabilir: 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

Neden düşünmeye değer? NumPy işlevleri genellikle düşük ek yük nedeniyle panda eşdeğerlerinden biraz daha hızlıdır. Bu, dizin hizalamasına bağlı olmayan elementwise bir işlem olduğundan, bu yöntemin pandalar için uygun bir yedek olmadığı çok az durum vardırisin .

Dize ile çalışırken panda yordamları genellikle yinelemelidir, çünkü dize işlemlerini vektörlemek zordur. Burada liste kavrayışının daha hızlı olacağını gösteren çok sayıda kanıt var. . inŞimdi bir çek için başvuruyoruz .

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

Bununla birlikte, belirtmek çok daha kullanışsızdır, bu yüzden ne yaptığınızı bilmiyorsanız kullanmayın.

Son olarak, bu cevaptaDataFrame.query ele alınanlar da vardır . numexpr FTW!


Hoşuma gitti, ama df3 din1 sütun olan bir sütun karşılaştırmak isterseniz ne olacak? Bu nasıl olurdu?
Arthur D. Howland

12

Genellikle böyle satırlar üzerinde genel filtreleme yapıyorum:

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

10
FYI, bu vektörize edilmiş @DSM soln'den çok daha yavaş
Jeff

@Jeff bunu beklerdim, ama doğrudan pandalarda bulunmayan bir şeyi filtrelemem gerektiğinde geri dönüyorum. (".Startwith veya regex eşleşmesi gibi) demek üzereydim, ama bunların hepsine sahip Series.str hakkında bilgi edindim!)
Kos

7

Ben de dfProfilesBusIds BUSINESS_ID olan bir BUSINESS_ID vardı dfbc satırları filtrelemek istedim

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

5
Yanlış ile karşılaştırmak yerine
isin'i

6

Cevaplardan olası çözümleri bir araya getirme:

IN için: df[df['A'].isin([3, 6])]

NOT IN iç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]))]


3
Bu çoğunlukla diğer cevaplardan gelen bilgileri tekrarlar. Kullanmak logical_not, ~operatörün ağız doludur .
cs95

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

uygulamak :

df[df.countries.isin(countries)]

diğer ülkelerde olduğu gibi uygulama :

df[df.countries.isin([x for x in np.unique(df.countries) if x not in countries])]
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.