पांडस डेटाफ्रेम को 'इन' और 'एसक्यूएल की तरह नहीं' का उपयोग करके कैसे फ़िल्टर करें


432

मैं एसक्यूएल के समकक्ष कैसे प्राप्त कर सकते 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'])]

लेकिन यह एक भयानक कीचड़ की तरह लगता है। क्या कोई इस पर सुधार कर सकता है?


1
मुझे लगता है कि आपका समाधान सबसे अच्छा समाधान है। तुम्हारा में कई कॉलम के NOT_IN को कवर किया जा सकता है।
ब्रूस जंग

क्या आप एकल स्तंभ या एकाधिक स्तंभों पर परीक्षण करना चाहते हैं?
स्माइली

1
संबंधित (प्रदर्शन / पांडा इंटर्नल्स
jpp

जवाबों:


820

आप उपयोग कर सकते हैं pd.Series.isin

"IN" उपयोग के लिए: something.isin(somewhere)

या "में नहीं" के लिए: ~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

1
सिर्फ एक FYI करें, @LondonRob के पास उनका DataFrame था और आपकी एक Series है। DataFrame isinको .13 में जोड़ा गया था।
टॉमएग्सपर्गर

पांडा 0.12.0 के साथ ऐसा करने के लिए कोई सुझाव? यह वर्तमान रिलीज़ किया गया संस्करण है। (शायद मुझे सिर्फ 0.13 के लिए इंतजार करना चाहिए?)
लंदनआरओबी

यदि आप वास्तव में 1-आयामी सरणियों (जैसे आप उदाहरण में) के साथ काम कर रहे हैं, तो आप पहली पंक्ति में डेटाफ़्रेम के बजाय एक श्रृंखला का उपयोग करते हैं, जैसे @DSM का उपयोग किया जाता है:df = pd.Series({'countries':['US','UK','Germany','China']})
TomAugspurger

2
@TomAugspurger: हमेशा की तरह, मुझे शायद कुछ याद आ रहा है। df, मेरा और उसका, दोनों एक है DataFramecountriesएक सूची है। df[~df.countries.isin(countries)]एक पैदा करता है DataFrame, नहीं Series, और 0.11.0.dev-14a04dd में भी वापस काम करने लगता है।
DSM

7
यह उत्तर भ्रमित करने वाला है क्योंकि आप countriesचर का पुन: उपयोग करते रहते हैं। ठीक है, ओपी इसे करता है, और यह विरासत में मिला है, लेकिन कुछ ऐसा है जो पहले बुरी तरह से किया गया था अब इसे बुरी तरह से करने का औचित्य नहीं है।
ifly6

63

वैकल्पिक समाधान जो .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

10
@LondonRob queryअब प्रायोगिक नहीं है।
पॉल रूजियक्स

38

कैसे एक पांडा डेटा के लिए 'में' और 'नहीं' को लागू करने के लिए?

पांडा प्रस्तावों दो तरीकों: Series.isinऔर DataFrame.isinसीरीज और DataFrames, क्रमशः के लिए।


एक कॉलम के आधार पर डेटाफ़्रेम फ़िल्टर करें (यह श्रृंखला पर भी लागू होता है)

isinडेटाफ़्रेम में पंक्तियों को फ़िल्टर करने के लिए सबसे आम परिदृश्य एक विशिष्ट कॉलम पर एक शर्त लागू कर रहा है।

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

मैनी कॉलम पर फ़िल्टर करें

कभी-कभी, आप कई कॉलमों में कुछ खोज शब्दों के साथ 'इन' सदस्यता जांच लागू करना चाहेंगे।

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

इससे, पंक्तियों को बनाए रखने के लिए जहां कम से कम एक स्तंभ हैTrue , हम anyपहली अक्ष के साथ उपयोग कर सकते हैं :

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, सूची comprehensions (स्ट्रिंग डेटा)

ऊपर वर्णित विधियों के अतिरिक्त, आप सुन्न समकक्ष का भी उपयोग कर सकते हैं 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

यह विचार करने लायक क्यों है? लोअरहेड के कारण नंबरी फंक्शन आमतौर पर अपने पंडों के समकक्षों की तुलना में थोड़ा तेज होते हैं। चूंकि यह एक एलिमेंट वाइज ऑपरेशन है जो इंडेक्स अलाइनमेंट पर निर्भर नहीं करता है, ऐसे बहुत कम परिस्थितियां हैं जहां यह विधि पांडा के लिए एक उपयुक्त प्रतिस्थापन नहीं है 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!


मुझे यह पसंद है, लेकिन क्या होगा अगर मैं df3 में एक स्तंभ की तुलना करना चाहता हूं जो कि df1 कॉलम है? वो कैसा लगता है?
आर्थर डी। हावलैंड

12

मैं आम तौर पर इस तरह पंक्तियों पर सामान्य फ़िल्टरिंग कर रहा हूं:

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

10
FYI करें, यह @DSM सॉल की तुलना में बहुत धीमा है जो कि वेक्टरकृत है
जेफ

@ जेफ़ मुझे उम्मीद है कि, लेकिन यह है कि जब मैं सीधे पंडों में कुछ अनुपलब्ध पर फ़िल्टर करने की आवश्यकता होती है तो मैं वापस आ जाता हूं। (मैं कहने जा रहा था "जैसे .startwith या regex मिलान, लेकिन बस Series.str के बारे में पता चला कि यह सब!)
कोस

7

मैं dfbc पंक्तियों को फ़िल्टर करना चाहता था जिसमें एक BUSINESS_ID था जो dfProfilesBusIds के BUSINESS_ID में भी था

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

5
आप झूठी
OneCricketeer

6

उत्तरों से संभावित समाधानों को समाप्‍त करना:

अंदर के लिए: df[df['A'].isin([3, 6])]

में नहीं:

  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
यह ज्यादातर अन्य उत्तरों की जानकारी को दोहराता है। का उपयोग करना ऑपरेटर के logical_notएक मुखर समकक्ष है ~
CS95

3
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])]
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.