দুটি ডাটাফ্রেমের সাথে তুলনা করা এবং পার্থক্যগুলি পাওয়া


89

আমার দুটি ডাটাফ্রেম রয়েছে। উদাহরণ:

df1:
Date       Fruit  Num  Color 
2013-11-24 Banana 22.1 Yellow
2013-11-24 Orange  8.6 Orange
2013-11-24 Apple   7.6 Green
2013-11-24 Celery 10.2 Green

df2:
Date       Fruit  Num  Color 
2013-11-24 Banana 22.1 Yellow
2013-11-24 Orange  8.6 Orange
2013-11-24 Apple   7.6 Green
2013-11-24 Celery 10.2 Green
2013-11-25 Apple  22.1 Red
2013-11-25 Orange  8.6 Orange

প্রতিটি ডাটাফ্রেমের সূচি হিসাবে তারিখ থাকে। উভয় ডেটাফ্রেমে একই কাঠামো রয়েছে।

আমি যা করতে চাই, তা এই দুটি ডাটাফ্রেমের সাথে তুলনা করা এবং এটি সন্ধান করুন যে সারিগুলি ডিএফ 2 এ ডিফ 1 এ নেই in আমি তারিখ (সূচী) এবং প্রথম কলাম (কলা, অ্যাপল, ইত্যাদি) তুলনা করতে চাই যে তারা ডিএফ 2 বনাম ডিএফ 1 এ রয়েছে কিনা তা দেখতে।

আমি নিম্নলিখিত চেষ্টা করেছি:

প্রথম পদ্ধতির জন্য আমি এই ত্রুটিটি পেয়েছি: "ব্যতিক্রম: কেবলমাত্র অভিন্ন-লেবেলযুক্ত ডেটা ফ্রেম অবজেক্টগুলি তুলনা করতে পারে" । আমি সূচি হিসাবে তারিখটি অপসারণ করার চেষ্টা করেছি কিন্তু একই ত্রুটি পেয়েছি।

উপর তৃতীয় পদ্ধতির , আমি মিথ্যা ফিরে জাহির পেতে কিন্তু চিন্তা করতে পারে না কিভাবে আসলে বিভিন্ন সারি দেখতে।

যে কোনও পয়েন্টার স্বাগত জানানো হবে


আপনি যদি এটি করেন: cookbook-r.com/Manipulating_data/… , এটি কী 'অভিন্ন-লেবেলযুক্ত ডেটা ফ্রেম অবজেক্টস' ব্যতিক্রম থেকে মুক্তি পাবে?
অ্যান্টনি কং

কোনও ভাগ্য ছাড়াই সমস্যাটি ঘুরে দেখার চেষ্টা করার জন্য আমি বহুবার কলামের নাম পরিবর্তন করেছি।
এরিক ডি ব্রাউন

4
FWIW, আমি কলামের নামগুলি উভয় ডেটাফ্রেমে "a, b, c, d" হিসাবে পরিবর্তন করেছি এবং একই ত্রুটি বার্তা পেয়েছি।
এরিক ডি ব্রাউন

উত্তর:


105

এই পদ্ধতির, df1 != df2শুধুমাত্র অভিন্ন সারি এবং কলামগুলির সাথে ডেটা ফ্রেমগুলির জন্য কাজ করে। প্রকৃতপক্ষে, সমস্ত ডেটাফ্রেম অক্ষকে _indexed_sameপদ্ধতির সাথে তুলনা করা হয় , এবং ব্যতিক্রমগুলি পাওয়া গেলে, এমনকি কলাম / সূচী ক্রমেও ব্যতিক্রম উত্থাপিত হয়।

যদি আমি আপনাকে সঠিকভাবে বুঝতে পারি তবে আপনি পরিবর্তনগুলি খুঁজে পেতে চান না, তবে প্রতিসম পার্থক্য। তার জন্য, একটি পদ্ধতির ডেটাফ্রেমগুলি সংমিশ্রণ হতে পারে:

>>> df = pd.concat([df1, df2])
>>> df = df.reset_index(drop=True)

দ্বারা গ্রুপ

>>> df_gpby = df.groupby(list(df.columns))

অনন্য রেকর্ডের সূচক পান

>>> idx = [x[0] for x in df_gpby.groups.values() if len(x) == 1]

ছাঁকনি

>>> df.reindex(idx)
         Date   Fruit   Num   Color
9  2013-11-25  Orange   8.6  Orange
8  2013-11-25   Apple  22.1     Red

এই ছিল উত্তর। আমি "তারিখ" সূচক মুছে ফেলেছি এবং এই পদ্ধতির অনুসরণ করেছি এবং আমি সঠিক আউটপুট পাই।
এরিক ডি ব্রাউন

10
Df1 থেকে df2 এ কোন সারিগুলি সরানো / যুক্ত / পরিবর্তন করা হয়েছে তা দেখার জন্য এখানে কী কোনও পতাকা যুক্ত করার সহজ উপায় আছে?
পাইকথন

@ আলকো আমি ভাবছিলাম, এটি কি pd.concatকেবলমাত্র অনুপস্থিত আইটেমগুলিতে যুক্ত করে df1? বা এটি df1সম্পূর্ণরূপে প্রতিস্থাপন করে df2?
জেক ওয়াং

@ জ্যাকওং pd.concat- যেমন এখানে ব্যবহৃত হয়েছে - একটি বাহ্যিক যোগদান করে। অন্য কথায়, এটি উভয় df প্রয়োগ থেকে সব সূচকের যোগদান করে এবং এই ডিফল্ট আচরণের জন্য আসলে pd.concat(), এখানে ডক্স এর pandas.pydata.org/pandas-docs/stable/merging.html
Thanos

পান্ডা ব্যবহার করে আমরা সর্বোচ্চ কত রেকর্ড তুলনা করতে পারি?
পিড

25

একটি অভিধানে উপসংহারে ডেটাফ্রেমগুলি পাস করার ফলে, একটি মাল্টি-ইনডেক্স ডেটাফ্রেমের ফলাফল হয় যা থেকে আপনি সহজেই ডুপ্লিকেটগুলি মুছতে পারেন, যার ফলস্বরূপ ডেটাফ্রেমের মধ্যে পার্থক্য সহ একাধিক সূচি ডেটাফ্রেম হয়:

import sys
if sys.version_info[0] < 3:
    from StringIO import StringIO
else:
    from io import StringIO
import pandas as pd

DF1 = StringIO("""Date       Fruit  Num  Color 
2013-11-24 Banana 22.1 Yellow
2013-11-24 Orange  8.6 Orange
2013-11-24 Apple   7.6 Green
2013-11-24 Celery 10.2 Green
""")
DF2 = StringIO("""Date       Fruit  Num  Color 
2013-11-24 Banana 22.1 Yellow
2013-11-24 Orange  8.6 Orange
2013-11-24 Apple   7.6 Green
2013-11-24 Celery 10.2 Green
2013-11-25 Apple  22.1 Red
2013-11-25 Orange  8.6 Orange""")


df1 = pd.read_table(DF1, sep='\s+')
df2 = pd.read_table(DF2, sep='\s+')
#%%
dfs_dictionary = {'DF1':df1,'DF2':df2}
df=pd.concat(dfs_dictionary)
df.drop_duplicates(keep=False)

ফলাফল:

             Date   Fruit   Num   Color
DF2 4  2013-11-25   Apple  22.1     Red
    5  2013-11-25  Orange   8.6  Orange

4
এটি একটি আরও সহজ পদ্ধতি, কেবলমাত্র আরও একটি রিভিশন এটি আরও সহজ করে তুলতে পারে। অভিধানে কনক্যাট করার দরকার নেই, df = pd.concat ব্যবহার করুন ([df1, df2]) একই কাজ করবে
লিঙ্গ

আপনার বিল্ট-ইন কীওয়ার্ডটি ওভাররাইট করা উচিত নয় dict!
denfromufa

কোন ডেটা ফ্রেমে অনন্য সারি রয়েছে তা নির্ধারণের জন্য কি এখানে যুক্ত করার কোনও উপায় আছে?
jlewkovich

আপনি মাল্টিইন্ডেক্সের প্রথম স্তরের মাধ্যমে বলতে পারবেন যা অভিধানে ডেটাফ্রেমের কীটি রয়েছে (আমি সঠিক কীগুলির সাহায্যে আউটপুট আপডেট করেছি)
জুর

25

আপডেট করা হচ্ছে এবং স্থাপন, কোথাও এটি অন্যদের খুঁজে পায় তার জন্য সহজ হবে, লিং 'উপর এর মন্তব্যে Jur উপরে এর প্রতিক্রিয়া।

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

এই ডেটা ফ্রেমগুলির সাথে পরীক্ষা করা:

# with import pandas as pd

df1 = pd.DataFrame({
    'Date':['2013-11-24','2013-11-24','2013-11-24','2013-11-24'],
    'Fruit':['Banana','Orange','Apple','Celery'],
    'Num':[22.1,8.6,7.6,10.2],
    'Color':['Yellow','Orange','Green','Green'],
    })

df2 = pd.DataFrame({
    'Date':['2013-11-24','2013-11-24','2013-11-24','2013-11-24','2013-11-25','2013-11-25'],
    'Fruit':['Banana','Orange','Apple','Celery','Apple','Orange'],
    'Num':[22.1,8.6,7.6,10.2,22.1,8.6],
    'Color':['Yellow','Orange','Green','Green','Red','Orange'],
    })

এর ফলাফল:

# for df1

         Date   Fruit   Num   Color
0  2013-11-24  Banana  22.1  Yellow
1  2013-11-24  Orange   8.6  Orange
2  2013-11-24   Apple   7.6   Green
3  2013-11-24  Celery  10.2   Green


# for df2

         Date   Fruit   Num   Color
0  2013-11-24  Banana  22.1  Yellow
1  2013-11-24  Orange   8.6  Orange
2  2013-11-24   Apple   7.6   Green
3  2013-11-24  Celery  10.2   Green
4  2013-11-25   Apple  22.1     Red
5  2013-11-25  Orange   8.6  Orange


# for df_diff

         Date   Fruit   Num   Color
4  2013-11-25   Apple  22.1     Red
5  2013-11-25  Orange   8.6  Orange

5

ফিল্টারিং ধাপটি (যেখানে আমি পেয়েছি ValueError: cannot reindex from a duplicate axis) ব্যতীত আমার জন্য প্রায় আমার জন্য কাজ করা আলকোর জবাব তৈরি করা , এখানে আমি ব্যবহার করেছি চূড়ান্ত সমাধান:

# join the dataframes
united_data = pd.concat([data1, data2, data3, ...])
# group the data by the whole row to find duplicates
united_data_grouped = united_data.groupby(list(united_data.columns))
# detect the row indices of unique rows
uniq_data_idx = [x[0] for x in united_data_grouped.indices.values() if len(x) == 1]
# extract those unique values
uniq_data = united_data.iloc[uniq_data_idx]

উত্তরের সাথে চমৎকার যোগ। ধন্যবাদ
এরিক ডি ব্রাউন

4
আমি ত্রুটিটি পাচ্ছি, ' IndexError: index out of bounds', যখন আমি তৃতীয় লাইনটি চালানোর চেষ্টা করি।
মুনড্রা

5
# THIS WORK FOR ME

# Get all diferent values
df3 = pd.merge(df1, df2, how='outer', indicator='Exist')
df3 = df3.loc[df3['Exist'] != 'both']


# If you like to filter by a common ID
df3  = pd.merge(df1, df2, on="Fruit", how='outer', indicator='Exist')
df3  = df3.loc[df3['Exist'] != 'both']

এটি সেরা উত্তর
মোশেইভি

3

একটি সহজ সমাধান যা দ্রুত এবং ভাল, এবং সংখ্যাগুলি পৃথক হলে আপনাকে পরিমাণের পার্থক্যও দিতে পারে:

df1_i = df1.set_index(['Date','Fruit','Color'])
df2_i = df2.set_index(['Date','Fruit','Color'])
df_diff = df1_i.join(df2_i,how='outer',rsuffix='_').fillna(0)
df_diff = (df_diff['Num'] - df_diff['Num_'])

এখানে df_diff পার্থক্যের একটি সংক্ষিপ্তসার। আপনি পরিমাণে পার্থক্য খুঁজতে এটি ব্যবহার করতে পারেন। আপনার উদাহরণে:

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

ব্যাখ্যা: একইভাবে দুটি তালিকার তুলনা করার জন্য, দক্ষতার সাথে এটি করার জন্য আমাদের প্রথমে তাদের তুলনা করার আদেশ দেওয়া উচিত (তালিকাটিকে সেট / হ্যাশিংয়ে রূপান্তর করাও দ্রুত হবে; উভয়ই সাধারণ ও (এন ^ 2) ডাবল তুলনা লুপের জন্য অবিশ্বাস্য উন্নতি

দ্রষ্টব্য: নিম্নলিখিত কোডটি সারণী তৈরি করে:

df1=pd.DataFrame({
    'Date':['2013-11-24','2013-11-24','2013-11-24','2013-11-24'],
    'Fruit':['Banana','Orange','Apple','Celery'],
    'Num':[22.1,8.6,7.6,10.2],
    'Color':['Yellow','Orange','Green','Green'],
})
df2=pd.DataFrame({
    'Date':['2013-11-24','2013-11-24','2013-11-24','2013-11-24','2013-11-25','2013-11-25'],
    'Fruit':['Banana','Orange','Apple','Celery','Apple','Orange'],
    'Num':[22.1,8.6,7.6,10.2,22.1,8.6],
    'Color':['Yellow','Orange','Green','Green','Red','Orange'],
})

3

এখানে একটি সহজ সমাধানের প্রতিষ্ঠাতা:

https://stackoverflow.com/a/47132808/9656339

pd.concat([df1, df2]).loc[df1.index.symmetric_difference(df2.index)]


4
স্ট্যাক ওভারফ্লো টম 2 শোসে স্বাগতম। দয়া করে লিঙ্ক-কেবল উত্তর সরবরাহ করবেন না, লিঙ্কটি থেকে সামগ্রীটি বের করার চেষ্টা করুন এবং কেবলমাত্র একটি রেফারেন্স হিসাবে রেখে দিন (লিঙ্কের সামগ্রীটি মুছতে পারে বা লিঙ্কটি নিজেই ভেঙে যেতে পারে)। আরও তথ্যের জন্য "আমি কীভাবে একটি ভাল উত্তর লিখব?" । আপনি যদি বিশ্বাস করেন যে এই প্রশ্নের ইতিমধ্যে অন্য একটি প্রশ্নের উত্তর দেওয়া হয়েছিল, দয়া করে এটি সদৃশ হিসাবে চিহ্নিত করুন।
জিজিজি

2
# given
df1=pd.DataFrame({'Date':['2013-11-24','2013-11-24','2013-11-24','2013-11-24'],
    'Fruit':['Banana','Orange','Apple','Celery'],
    'Num':[22.1,8.6,7.6,10.2],
    'Color':['Yellow','Orange','Green','Green']})
df2=pd.DataFrame({'Date':['2013-11-24','2013-11-24','2013-11-24','2013-11-24','2013-11-25','2013-11-25'],
    'Fruit':['Banana','Orange','Apple','Celery','Apple','Orange'],
    'Num':[22.1,8.6,7.6,1000,22.1,8.6],
    'Color':['Yellow','Orange','Green','Green','Red','Orange']})

# find which rows are in df2 that aren't in df1 by Date and Fruit
df_2notin1 = df2[~(df2['Date'].isin(df1['Date']) & df2['Fruit'].isin(df1['Fruit']) )].dropna().reset_index(drop=True)

# output
print('df_2notin1\n', df_2notin1)
#      Color        Date   Fruit   Num
# 0     Red  2013-11-25   Apple  22.1
# 1  Orange  2013-11-25  Orange   8.6

2

যেহেতু pandas >= 1.1.0আমাদের আছে DataFrame.compareএবং Series.compare

দ্রষ্টব্য: পদ্ধতিটি কেবল অভিন্ন লেবেলযুক্ত ডেটা ফ্রেম অবজেক্টগুলির সাথে তুলনা করতে পারে, এর অর্থ অভিন্ন সারি এবং কলাম লেবেলের সাথে ডেটা ফ্রেম।

df1 = pd.DataFrame({'A': [1, 2, 3],
                    'B': [4, 5, 6],
                    'C': [7, np.NaN, 9]})

df2 = pd.DataFrame({'A': [1, 99, 3],
                    'B': [4, 5, 81],
                    'C': [7, 8, 9]})

   A  B    C
0  1  4  7.0
1  2  5  NaN
2  3  6  9.0 

    A   B  C
0   1   4  7
1  99   5  8
2   3  81  9
df1.compare(df2)

     A          B          C      
  self other self other self other
1  2.0  99.0  NaN   NaN  NaN   8.0
2  NaN   NaN  6.0  81.0  NaN   NaN

এই তথ্যের জন্য আপনাকে ধন্যবাদ। আমি এখনও 1.1 এ স্থানান্তরিত হয়নি, তবে এটি জেনে রাখা ভাল।
এরিক ডি ব্রাউন

1

আমি এই সমাধান পেয়েছি। এটি কি আপনাকে সাহায্য করে?

text = """df1:
2013-11-24 Banana 22.1 Yellow
2013-11-24 Orange 8.6 Orange
2013-11-24 Apple 7.6 Green
2013-11-24 Celery 10.2 Green

df2:
2013-11-24 Banana 22.1 Yellow
2013-11-24 Orange 8.6 Orange
2013-11-24 Apple 7.6 Green
2013-11-24 Celery 10.2 Green
2013-11-25 Apple 22.1 Red
2013-11-25 Orange 8.6 Orange



argetz45
2013-11-24 Banana 22.1 Yellow
2013-11-24 Orange 118.6 Orange
2013-11-24 Apple 74.6 Green
2013-11-24 Celery 10.2 Green
2013-11-25     Nuts    45.8 Brown
2013-11-25 Apple 22.1 Red
2013-11-25 Orange 8.6 Orange
2013-11-26   Pear 102.54    Pale"""

from collections import OrderedDict
import re

r = re.compile('([a-zA-Z\d]+).*\n'
               '(20\d\d-[01]\d-[0123]\d.+\n?'
               '(.+\n?)*)'
               '(?=[ \n]*\Z'
                  '|'
                  '\n+[a-zA-Z\d]+.*\n'
                  '20\d\d-[01]\d-[0123]\d)')

r2 = re.compile('((20\d\d-[01]\d-[0123]\d) +([^\d.]+)(?<! )[^\n]+)')

d = OrderedDict()
bef = []

for m in r.finditer(text):
    li = []
    for x in r2.findall(m.group(2)):
        if not any(x[1:3]==elbef for elbef in bef):
            bef.append(x[1:3])
            li.append(x[0])
    d[m.group(1)] = li


for name,lu in d.iteritems():
    print '%s\n%s\n' % (name,'\n'.join(lu))

ফলাফল

df1
2013-11-24 Banana 22.1 Yellow
2013-11-24 Orange 8.6 Orange
2013-11-24 Apple 7.6 Green
2013-11-24 Celery 10.2 Green

df2
2013-11-25 Apple 22.1 Red
2013-11-25 Orange 8.6 Orange

argetz45
2013-11-25     Nuts    45.8 Brown
2013-11-26   Pear 102.54    Pale

সাহায্যের জন্য ধন্যবাদ. আমি উত্তর @ আলকো দ্বারা দেখেছি এবং কোডটি ভালভাবে কাজ করেছে।
এরিক ডি ব্রাউন

0

একটি লক্ষণীয় গুরুত্বপূর্ণ বিশদটি হ'ল আপনার ডেটাতে নকল সূচকের মান রয়েছে , তাই যে কোনও সরল তুলনা সম্পাদন করার জন্য আমাদের সবকিছুকে অনন্য হিসাবে পরিণত করা দরকার df.reset_index()এবং তাই আমরা শর্তের ভিত্তিতে নির্বাচনগুলি সম্পাদন করতে পারি। আপনার ক্ষেত্রে সূচকটি সংজ্ঞায়িত হয়ে গেলে, আমি ধরে নিই যে আপনি ডি সূচকটি রাখতে চান তাই একটি লাইন সমাধান রয়েছে:

[~df2.reset_index().isin(df1.reset_index())].dropna().set_index('Date')

পাইথোনিক দৃষ্টিকোণ থেকে উদ্দেশ্যটি একবারে পাঠযোগ্যতার উন্নতি করা, আমরা কিছুটা ভাঙ্গতে পারি:

# keep the index name, if it does not have a name it uses the default name
index_name = df.index.name if df.index.name else 'index' 

# setting the index to become unique
df1 = df1.reset_index()
df2 = df2.reset_index()

# getting the differences to a Dataframe
df_diff = df2[~df2.isin(df1)].dropna().set_index(index_name)

0

আশা করি এটি আপনার কাজে আসবে। ^ o ^

df1 = pd.DataFrame({'date': ['0207', '0207'], 'col1': [1, 2]})
df2 = pd.DataFrame({'date': ['0207', '0207', '0208', '0208'], 'col1': [1, 2, 3, 4]})
print(f"df1(Before):\n{df1}\ndf2:\n{df2}")
"""
df1(Before):
   date  col1
0  0207     1
1  0207     2

df2:
   date  col1
0  0207     1
1  0207     2
2  0208     3
3  0208     4
"""

old_set = set(df1.index.values)
new_set = set(df2.index.values)
new_data_index = new_set - old_set
new_data_list = []
for idx in new_data_index:
    new_data_list.append(df2.loc[idx])

if len(new_data_list) > 0:
    df1 = df1.append(new_data_list)
print(f"df1(After):\n{df1}")
"""
df1(After):
   date  col1
0  0207     1
1  0207     2
2  0208     3
3  0208     4
"""

0

আমি এই পদ্ধতিটি চেষ্টা করেছিলাম, এবং এটি কার্যকর হয়েছে। আমি আশা করি এটিও সহায়তা করতে পারে:

"""Identify differences between two pandas DataFrames"""
df1.sort_index(inplace=True)
df2.sort_index(inplace=True)
df_all = pd.concat([df1, df12], axis='columns', keys=['First', 'Second'])
df_final = df_all.swaplevel(axis='columns')[df1.columns[1:]]
df_final[df_final['change this to one of the columns'] != df_final['change this to one of the columns']]
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.