এসকিউএল এর মতো 'ইন' এবং 'ইন না' ব্যবহার করে পান্ডাস ডেটাফ্রেম কীভাবে ফিল্টার করবেন


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
আমি মনে করি আপনার সমাধানটিই সেরা সমাধান। আপনার একাধিক কলামের IN, NOT_IN কভার করতে পারে।
ব্রুস জং

আপনি কি একক কলাম বা একাধিক কলামে পরীক্ষা করতে চান?
smci 20

1
সম্পর্কিত (পারফরম্যান্স / পান্ডস ইন্টার্নাল
জেপ্পি

উত্তর:


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
কেবলমাত্র একটি এফওয়াইআই, @ লন্ডনরব তার ডেটাফ্রেম হিসাবে এবং আপনার একটি সিরিজ। ডেটাফ্রেমগুলি isin.13 এ যুক্ত হয়েছিল।
টমআগস্পারগার

পান্ডাস 0.12.0 দিয়ে এটি কীভাবে করবেন তার জন্য কোনও পরামর্শ? এটি বর্তমান প্রকাশিত সংস্করণ। (সম্ভবত আমার কেবল 0.13 অপেক্ষা করা উচিত ?!)
লন্ডন রব

যদি আপনি আসলে 1-মাত্রিক অ্যারেগুলি নিয়ে কাজ করে থাকেন (যেমন আপনি উদাহরণস্বরূপ) তবে আপনি প্রথম লাইনটি ডেটাফ্রেমের পরিবর্তে একটি সিরিজ ব্যবহার করছেন, যেমন @ ডিএসএম ব্যবহার করা হয়েছে:df = pd.Series({'countries':['US','UK','Germany','China']})
টমআগস্পারগার

2
@ টমআগস্পারগার: যথারীতি আমিও সম্ভবত কিছু অনুপস্থিত। dfআমার এবং তার উভয়ই হ'ল একটি DataFramecountriesএকটি তালিকা। df[~df.countries.isin(countries)]একটি DataFrameনা, উত্পাদন করে Seriesএবং 0.11.0.dev-14a04dd তেও ফিরে কাজ করবে বলে মনে হচ্ছে।
ডিএসএম

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
@ লন্ডনরব queryআর পরীক্ষামূলক নয়।
পল রাউজিক্স

38

পান্ডাস ডেটাফ্রেমের জন্য কীভাবে 'ইন' এবং 'ইন ইন' বাস্তবায়ন করবেন?

পান্ডাস দুটি পদ্ধতি প্রস্তাব করে: Series.isinএবং DataFrame.isinসিরিজ এবং ডেটা ফ্রেমের জন্য যথাক্রমে।


এক কলামের উপর ভিত্তি করে ফিল্টার ডেটা ফ্রেম (সিরিজের ক্ষেত্রেও প্রযোজ্য)

সর্বাধিক সাধারণ 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"ক" এবং "বি" উভয় কলামে শর্ত প্রয়োগ করতে , ব্যবহার করুন 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 তালিকা উপলব্ধি (স্ট্রিং ডেটা)

উপরে বর্ণিত পদ্ধতিগুলি ছাড়াও, আপনি নিমপি সমতুল্য: ব্যবহার করতে পারেন 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 ফাংশনগুলি তাদের প্যান্ডাস সমতুল্যগুলির তুলনায় সাধারণত কিছুটা দ্রুত হয়। যেহেতু এটি একটি মৌলিক পদক্ষেপ যা সূচক প্রান্তিককরণের উপর নির্ভর করে না, খুব কম পরিস্থিতি রয়েছে যেখানে এই পদ্ধতিটি পান্ডাদের উপযুক্ত প্রতিস্থাপন নয় '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 এফটিডব্লিউ!


আমি এটি পছন্দ করি তবে আমি কী চাই যদি ডিএফ 3 এর একটি কলামের সাথে ডিফ 1 কলামটি তুলনা করতে পারি? দেখতে কেমন লাগবে?
আর্থার ডি হাওল্যান্ড

12

আমি সাধারণত সারিগুলিতে জেনেরিক ফিল্টারিং করছি:

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

10
এফওয়াইআই, এটি ভেক্টরাইজড @ ডিএমএস সলানের চেয়ে অনেক ধীর
জেফ

@ জেফ আমি এটি প্রত্যাশা করছিলাম, তবে আমি যখন প্যান্ডাসে অনুপলব্ধ কিছুতে সরাসরি ফিল্টার করার দরকার পড়ি তখন আমি ফিরে আসি। (আমি "স্টার্ট বা রেইগেক্স ম্যাচিংয়ের কথা বলতে যাচ্ছিলাম, তবে কেবল সিরিজ সম্পর্কে জানতে পেরেছি। এতে সমস্ত কিছু রয়েছে!)
কোস


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])]
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.