Saya memiliki dua dataframe. Contoh:
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
Setiap kerangka data memiliki Tanggal sebagai indeks. Kedua kerangka data memiliki struktur yang sama.
Apa yang ingin saya lakukan adalah membandingkan kedua dataframe ini dan menemukan baris mana yang ada di df2 yang tidak ada di df1. Saya ingin membandingkan tanggal (indeks) dan kolom pertama (Banana, APple, dll) untuk melihat apakah keduanya ada di df2 vs df1.
Saya telah mencoba yang berikut ini:
- Menghasilkan perbedaan dalam dua bingkai data Pandas secara berdampingan - menyoroti perbedaannya
- Membandingkan dua kerangka data panda untuk mengetahui perbedaannya
Untuk pendekatan pertama saya mendapatkan kesalahan ini: "Pengecualian: Hanya dapat membandingkan objek DataFrame berlabel identik" . Saya telah mencoba menghapus Tanggal sebagai indeks tetapi mendapatkan kesalahan yang sama.
Pada pendekatan ketiga , saya mendapatkan pernyataan untuk mengembalikan False tetapi tidak dapat menemukan cara untuk benar-benar melihat baris yang berbeda.
Setiap petunjuk akan diterima
Jawaban:
Pendekatan ini,,
df1 != df2
hanya berfungsi untuk kerangka data dengan baris dan kolom yang identik. Faktanya, semua sumbu kerangka data dibandingkan dengan_indexed_same
metode, dan pengecualian dimunculkan jika ditemukan perbedaan, bahkan dalam urutan kolom / indeks.Jika saya membuat Anda benar, Anda tidak ingin menemukan perubahan, tetapi perbedaan simetris. Untuk itu, satu pendekatan mungkin menggabungkan kerangka data:
>>> df = pd.concat([df1, df2]) >>> df = df.reset_index(drop=True)
dikelompokkan menurut
>>> df_gpby = df.groupby(list(df.columns))
dapatkan indeks catatan unik
>>> idx = [x[0] for x in df_gpby.groups.values() if len(x) == 1]
Saring
>>> df.reindex(idx) Date Fruit Num Color 9 2013-11-25 Orange 8.6 Orange 8 2013-11-25 Apple 22.1 Red
sumber
pd.concat
menambahkan hanya item yang hilang daridf1
? Atau apakah itudf1
sepenuhnya diganti dengandf2
?pd.concat
- seperti yang digunakan di sini - melakukan gabungan luar. Dengan kata lain, ini menggabungkan semua indeks dari kedua df dan ini sebenarnya adalah perilaku default untukpd.concat()
, inilah docs pandas.pydata.org/pandas-docs/stable/merging.htmlMeneruskan kerangka data untuk digabungkan dalam kamus, menghasilkan kerangka data multi-indeks yang darinya Anda dapat dengan mudah menghapus duplikat, yang menghasilkan kerangka data multi-indeks dengan perbedaan antara kerangka data:
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)
Hasil:
Date Fruit Num Color DF2 4 2013-11-25 Apple 22.1 Red 5 2013-11-25 Orange 8.6 Orange
sumber
dict
!Memperbarui dan menempatkan, di suatu tempat akan lebih mudah ditemukan oleh orang lain, ling komentar atas tanggapan juri di atas.
df_diff = pd.concat([df1,df2]).drop_duplicates(keep=False)
Menguji dengan DataFrames ini:
# 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'], })
Hasil ini:
# 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
sumber
Berdasarkan jawaban alko yang hampir berhasil untuk saya, kecuali untuk langkah pemfilteran (di mana saya mendapatkan :)
ValueError: cannot reindex from a duplicate axis
, berikut adalah solusi terakhir yang saya gunakan:# 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]
sumber
IndexError: index out of bounds'
, ketika saya mencoba menjalankan baris ketiga.# 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']
sumber
Ada solusi yang lebih sederhana yang lebih cepat dan lebih baik, dan jika jumlahnya berbeda bahkan dapat memberi Anda perbedaan kuantitas:
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_'])
Berikut df_diff adalah sinopsis dari perbedaannya. Anda bahkan dapat menggunakannya untuk mencari perbedaan jumlah. Dalam contoh Anda:
Penjelasan: Sama halnya dengan membandingkan dua daftar, untuk melakukannya secara efisien kita harus terlebih dahulu memesannya kemudian membandingkannya (mengonversi daftar menjadi set / hashing juga akan cepat; keduanya merupakan peningkatan yang luar biasa pada loop perbandingan ganda O (N ^ 2) sederhana
Catatan: kode berikut menghasilkan tabel:
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'], })
sumber
Pendiri solusi sederhana di sini:
https://stackoverflow.com/a/47132808/9656339
pd.concat([df1, df2]).loc[df1.index.symmetric_difference(df2.index)]
sumber
# 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
sumber
Sejak
pandas >= 1.1.0
kami memilikiDataFrame.compare
danSeries.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
sumber
Saya mendapat solusi ini. Apakah ini membantu Anda?
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))
hasil
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
sumber
Satu detail penting untuk diperhatikan adalah bahwa data Anda memiliki nilai indeks duplikat , jadi untuk melakukan perbandingan langsung apa pun, kami perlu mengubah semuanya menjadi unik
df.reset_index()
dan karena itu kami dapat melakukan pemilihan berdasarkan kondisi. Setelah dalam kasus Anda indeks ditentukan, saya berasumsi bahwa Anda ingin menyimpan de index sehingga ada solusi satu baris:[~df2.reset_index().isin(df1.reset_index())].dropna().set_index('Date')
Setelah tujuan dari sudut pandang pythonic adalah untuk meningkatkan keterbacaan, kita dapat sedikit merusak:
# 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)
sumber
Semoga bermanfaat bagi Anda. ^ 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 """
sumber
Saya mencoba metode ini, dan berhasil. Saya harap ini bisa membantu juga:
"""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']]
sumber