পাইথন পান্ডাস - দুটি ডেটা ফ্রেমের মধ্যে পার্থক্য সন্ধান করুন


98

আমার দুটি ডেটা ফ্রেম df1 এবং df2 রয়েছে, যেখানে df2 হল df1 এর একটি উপসেট। আমি কীভাবে একটি নতুন ডেটা ফ্রেম (df3) পেতে পারি যা দুটি ডেটা ফ্রেমের মধ্যে পার্থক্য?

অন্য কথায়, একটি ডেটা ফ্রেম যা df1 এ থাকা সমস্ত সারি / কলামগুলি df2 এ নেই?

এখানে চিত্র বর্ণনা লিখুন


4
এটি করার সহজতম উপায় আপনার ডেটাফ্রেমগুলি কীভাবে কাঠামোগত করা হয় তার উপর নির্ভর করবে (সূচীগুলি ব্যবহার করা যায় কিনা ইত্যাদি)। পান্ডাস প্রশ্নগুলিতে আপনার কেন সর্বদা পুনরুত্পাদনযোগ্য উদাহরণ অন্তর্ভুক্ত করা উচিত এটির একটি উত্তম উদাহরণ ।
কুমার 16

আমি ডেটাফ্রেম নমুনা চিত্র যুক্ত করেছি
userPyGeo

উত্তর:


152

ব্যবহার করে drop_duplicates

pd.concat([df1,df2]).drop_duplicates(keep=False)

Update :

Above method only working for those dataframes they do not have duplicate itself, For example

df1=pd.DataFrame({'A':[1,2,3,3],'B':[2,3,4,4]})
df2=pd.DataFrame({'A':[1],'B':[2]})

এটি নীচের মত আউটপুট হবে, যা ভুল

ভুল আউটপুট:

pd.concat([df1, df2]).drop_duplicates(keep=False)
Out[655]: 
   A  B
1  2  3

সঠিক আউটপুট

Out[656]: 
   A  B
1  2  3
2  3  4
3  3  4

কীভাবে অর্জন করব?

পদ্ধতি 1: ব্যবহার isinসঙ্গেtuple

df1[~df1.apply(tuple,1).isin(df2.apply(tuple,1))]
Out[657]: 
   A  B
1  2  3
2  3  4
3  3  4

পদ্ধতি 2: mergeসহindicator

df1.merge(df2,indicator = True, how='left').loc[lambda x : x['_merge']!='both']
Out[421]: 
   A  B     _merge
1  2  3  left_only
2  3  4  left_only
3  3  4  left_only

4
নকলগুলি খুঁজতে গিয়ে কোন কলামগুলি বিবেচনা করতে হবে তাও আপনি নির্ধারণ করতে পারেন:pd.concat([df1,df2]).drop_duplicates(subset = ['col1','col2'], keep=False)
Szpaqn

@ এসপ্যাকান লক্ষ্য করুন যে এই পদ্ধতিটি বিশেষ ক্ষেত্রে পরিচালনা করবে না। :-)
BEN_YO

নোট করুন যে এটির ফলে অপ্রত্যাশিত সারিগুলি ফলাফলের মধ্যে থাকতে পারে যদি আপনার ডেটা ধরণের একটি float(কারণ 12.00000000001 != 12) হয়। একটি আরও ভাল অনুশীলন হ'ল দুটি ডেটা ফ্রেমে আইডির সেট ছেদটি খুঁজে পাওয়া এবং তার উপর ভিত্তি করে পার্থক্য পাওয়া।
জিগাং

4
@ ডেটচনেট আপনার দুটি ডাটা ফ্রেমের একই নাম তৈরি করতে হবে
BEN_YO

4
পদ্ধতি 2 ( indicator=True) একটি অত্যন্ত বহুমুখী এবং দরকারী সরঞ্জাম, আমি এই উত্তরের শীর্ষে এটি দেখতে পছন্দ করতে চাই তবে 'বাহ্যিক' নয় 'বামে' সমস্ত 3 পরিস্থিতি কভার করতে যোগ দিতে চাই।
mirekphd

32

সারিগুলির জন্য, এটি চেষ্টা করুন, যেখানে Nameযৌথ সূচক কলামটি রয়েছে (একাধিক সাধারণ কলামগুলির জন্য তালিকা হতে পারে, বা নির্দিষ্ট করুন left_onএবং right_on):

m = df1.merge(df2, on='Name', how='outer', suffixes=['', '_'], indicator=True)

indicator=Trueযেমন একটি কলাম নামক যোগ সেটিং দরকারী _mergeমধ্যে সব পরিবর্তনের সঙ্গে df1এবং df23 সম্ভব ধরণের শ্রেণীবিভক্ত: "left_only", "right_only" বা "উভয়"।

কলামগুলির জন্য, এটি ব্যবহার করে দেখুন:

set(df1.columns).symmetric_difference(df2.columns)

8
ডাউনভোটার কি মন্তব্য করবেন? mergeসঙ্গে indicator=Trueদেওয়া ক্ষেত্র দ্বারা dataframes তুলনা জন্য আপনি ক্লাসিক সমাধান।
জেপ্পি

9

গৃহীত উত্তর 1 পদ্ধতিটি ভিতরে এনএএনএস সহ ডেটা ফ্রেমের জন্য কাজ করবে না pd.np.nan != pd.np.nan। এটি সর্বোত্তম উপায় কিনা তা আমি নিশ্চিত নই, তবে এটি এড়ানো যায়

df1[~df1.astype(str).apply(tuple, 1).isin(df2.astype(str).apply(tuple, 1))]

6

edit2, আমি সূচি নির্ধারণের প্রয়োজনীয়তা ছাড়াই একটি নতুন সমাধান বের করেছি

newdf=pd.concat[df1,df2].drop_duplicates(keep=False)

ঠিক আছে, আমি খুঁজে পেয়েছি সর্বোচ্চ ভোটের জবাবটিতে ইতিমধ্যে আমি যা আবিষ্কার করেছি তা রয়েছে Y হ্যাঁ, আমরা কেবল এই কোডটি এই শর্তে ব্যবহার করতে পারি যে প্রতি দুটি ডিএফ-তে কোনও সদৃশ নেই।


আমার কাছে একটি জটিল পদ্ধতি আছে method প্রথমটি আমরা প্রশ্নের দ্বারা প্রদত্ত দুটি ডাটাফ্রেমের সূচী হিসাবে 'নাম' সেট করি ince আমাদের দুটি ডিএফ-তে একই 'নাম' রয়েছে, তবে আমরা কেবল 'ছোট' ডিএফ এর সূচককে 'বড়' ডিএফ থেকে ফেলে দিতে পারি । কোডটি এখানে।

df1.set_index('Name',inplace=True)
df2.set_index('Name',inplace=True)
newdf=df1.drop(df2.index)

। আপনি সম্ভবত বোঝানো pd.concat ([df1, df2]) drop_duplicates (Keep = মিথ্যা)
Manaslu

4
import pandas as pd
# given
df1 = pd.DataFrame({'Name':['John','Mike','Smith','Wale','Marry','Tom','Menda','Bolt','Yuswa',],
    'Age':[23,45,12,34,27,44,28,39,40]})
df2 = pd.DataFrame({'Name':['John','Smith','Wale','Tom','Menda','Yuswa',],
    'Age':[23,12,34,44,28,40]})

# find elements in df1 that are not in df2
df_1notin2 = df1[~(df1['Name'].isin(df2['Name']) & df1['Age'].isin(df2['Age']))].reset_index(drop=True)

# output:
print('df1\n', df1)
print('df2\n', df2)
print('df_1notin2\n', df_1notin2)

# df1
#     Age   Name
# 0   23   John
# 1   45   Mike
# 2   12  Smith
# 3   34   Wale
# 4   27  Marry
# 5   44    Tom
# 6   28  Menda
# 7   39   Bolt
# 8   40  Yuswa
# df2
#     Age   Name
# 0   23   John
# 1   12  Smith
# 2   34   Wale
# 3   44    Tom
# 4   28  Menda
# 5   40  Yuswa
# df_1notin2
#     Age   Name
# 0   45   Mike
# 1   27  Marry
# 2   39   Bolt


'~' বুলিয়ান ইনডেক্সিংয়ের জন্য নয়। দেখুন: pandas.pydata.org/pandas-docs/stable/user_guide/…
স্পিডকোডার 5

3

অভিন্ন বা বিভিন্ন কলামের নাম সহ সম্ভবত একটি সহজ ওয়ান-লাইনার। Df2 ['Name2'] এর সদৃশ মান থাকা সত্ত্বেও কাজ করেছিল।

newDf = df1.set_index('Name1')
           .drop(df2['Name2'], errors='ignore')
           .reset_index(drop=False)

4
সহজ এবং কার্যকর। গন্তব্য মান উত্স (যেমন ছেদ) মধ্যে নেই এবং ক্ষেত্রে সূচকটি পুনরায় সেট করে এমন একটি ডিএফ এনেছে যা মূলটির সাথে সমান।
মিঃ

0

সুন্দর @ লিয়াংলির সমাধানের সামান্য প্রকরণের জন্য যা বিদ্যমান ডেটাফ্রেমগুলির সূচি পরিবর্তন করতে হবে না:

newdf = df1.drop(df1.join(df2.set_index('Name').index))

0

সূচক অনুসারে পার্থক্য সন্ধান করা। ধরে নিই df1 হল df2 এর একটি উপসেট এবং সূচকগুলি সাবসেট করার সময় এগিয়ে নেওয়া হয়

df1.loc[set(df1.index).symmetric_difference(set(df2.index))].dropna()

# Example

df1 = pd.DataFrame({"gender":np.random.choice(['m','f'],size=5), "subject":np.random.choice(["bio","phy","chem"],size=5)}, index = [1,2,3,4,5])

df2 =  df1.loc[[1,3,5]]

df1

 gender subject
1      f     bio
2      m    chem
3      f     phy
4      m     bio
5      f     bio

df2

  gender subject
1      f     bio
3      f     phy
5      f     bio

df3 = df1.loc[set(df1.index).symmetric_difference(set(df2.index))].dropna()

df3

  gender subject
2      m    chem
4      m     bio


0

স্বীকৃত উত্তর ছাড়াও, আমি আরও একটি আরও বিস্তৃত সমাধান প্রস্তাব করতে চাই যা কোনও / এর সাথে দুটি ডেফ্রেমের 2D সেট পার্থক্য খুঁজে পেতে পারে (তারা উভয় ডেট্রামের সাথে একযোগে মিলবে না)। এছাড়াও পদ্ধতি ডেটাফ্রেমের তুলনার জন্য উপাদানগুলির জন্য সহনশীলতা সেটআপ করতে দেয় (এটি ব্যবহার করে )indexcolumnsfloatnp.isclose


import numpy as np
import pandas as pd

def get_dataframe_setdiff2d(df_new: pd.DataFrame, 
                            df_old: pd.DataFrame, 
                            rtol=1e-03, atol=1e-05) -> pd.DataFrame:
    """Returns set difference of two pandas DataFrames"""

    union_index = np.union1d(df_new.index, df_old.index)
    union_columns = np.union1d(df_new.columns, df_old.columns)

    new = df_new.reindex(index=union_index, columns=union_columns)
    old = df_old.reindex(index=union_index, columns=union_columns)

    mask_diff = ~np.isclose(new, old, rtol, atol)

    df_bool = pd.DataFrame(mask_diff, union_index, union_columns)

    df_diff = pd.concat([new[df_bool].stack(),
                         old[df_bool].stack()], axis=1)

    df_diff.columns = ["New", "Old"]

    return df_diff

উদাহরণ:

In [1]

df1 = pd.DataFrame({'A':[2,1,2],'C':[2,1,2]})
df2 = pd.DataFrame({'A':[1,1],'B':[1,1]})

print("df1:\n", df1, "\n")

print("df2:\n", df2, "\n")

diff = get_dataframe_setdiff2d(df1, df2)

print("diff:\n", diff, "\n")
Out [1]

df1:
   A  C
0  2  2
1  1  1
2  2  2 

df2:
   A  B
0  1  1
1  1  1 

diff:
     New  Old
0 A  2.0  1.0
  B  NaN  1.0
  C  2.0  NaN
1 B  NaN  1.0
  C  1.0  NaN
2 A  2.0  NaN
  C  2.0  NaN 

0

পূর্বেই উল্লেখ করা হয়েছে এখানে যে

df1[~df1.apply(tuple,1).isin(df2.apply(tuple,1))]

সঠিক সমাধান তবে এটি ভুল আউটপুট উত্পন্ন করবে যদি

df1=pd.DataFrame({'A':[1],'B':[2]})
df2=pd.DataFrame({'A':[1,2,3,3],'B':[2,3,4,4]})

সেক্ষেত্রে উপরের সমাধানটি খালি ডেটাফ্রেম দেবে , পরিবর্তে concatপ্রতিটি ডাটাফ্রেম থেকে নকল অপসারণের পরে আপনার পদ্ধতিটি ব্যবহার করা উচিত ।

ব্যবহার concate with drop_duplicates

df1=df1.drop_duplicates(keep="first") 
df2=df2.drop_duplicates(keep="first") 
pd.concat([df1,df2]).drop_duplicates(keep=False)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.