Ich habe zwei Datenrahmen. Beispiele:
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
Jeder Datenrahmen hat das Datum als Index. Beide Datenrahmen haben die gleiche Struktur.
Was ich tun möchte, ist, diese beiden Datenrahmen zu vergleichen und herauszufinden, welche Zeilen in df2 sind, die nicht in df1 sind. Ich möchte das Datum (Index) und die erste Spalte (Banane, APple usw.) vergleichen, um festzustellen, ob sie in df2 und df1 vorhanden sind.
Ich habe folgendes versucht:
- Ausgabe von Unterschieden in zwei Pandas-Datenrahmen nebeneinander - Hervorheben des Unterschieds
- Vergleich zweier Pandas-Datenrahmen auf Unterschiede
Beim ersten Ansatz wird folgende Fehlermeldung angezeigt : "Ausnahme: Kann nur identisch beschriftete DataFrame-Objekte vergleichen" . Ich habe versucht, das Datum als Index zu entfernen, erhalte jedoch den gleichen Fehler.
Beim dritten Ansatz erhalte ich die Zusicherung, False zurückzugeben, kann aber nicht herausfinden, wie die verschiedenen Zeilen tatsächlich angezeigt werden.
Hinweise wären willkommen
Antworten:
Dieser Ansatz
df1 != df2
funktioniert nur für Datenrahmen mit identischen Zeilen und Spalten. Tatsächlich werden alle Datenrahmenachsen mit der_indexed_same
Methode verglichen , und es wird eine Ausnahme ausgelöst , wenn Unterschiede festgestellt werden, selbst in der Reihenfolge der Spalten / Indizes.Wenn ich Sie richtig verstanden habe, möchten Sie keine Änderungen finden, sondern symmetrische Unterschiede. Ein Ansatz könnte darin bestehen, Datenrahmen zu verketten:
>>> df = pd.concat([df1, df2]) >>> df = df.reset_index(drop=True)
gruppiere nach
>>> df_gpby = df.groupby(list(df.columns))
Index der eindeutigen Datensätze abrufen
>>> idx = [x[0] for x in df_gpby.groups.values() if len(x) == 1]
Filter
>>> df.reindex(idx) Date Fruit Num Color 9 2013-11-25 Orange 8.6 Orange 8 2013-11-25 Apple 22.1 Red
quelle
pd.concat
nur die fehlenden Elemente aus dem hinzudf1
? Oder ersetzt esdf1
komplett durchdf2
?pd.concat
- wie hier verwendet - führt eine äußere Verknüpfung durch. Mit anderen Worten, es verbindet alle Indizes von beiden df's und dies ist in der Tat das Standardverhalten fürpd.concat()
, hier ist die docs pandas.pydata.org/pandas-docs/stable/merging.htmlWenn Sie die Datenrahmen an concat in einem Wörterbuch übergeben, erhalten Sie einen Datenrahmen mit mehreren Indizes, aus dem Sie die Duplikate einfach löschen können. Dies führt zu einem Datenrahmen mit mehreren Indizes mit den Unterschieden zwischen den Datenrahmen:
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)
Ergebnis:
Date Fruit Num Color DF2 4 2013-11-25 Apple 22.1 Red 5 2013-11-25 Orange 8.6 Orange
quelle
dict
!Aktualisieren und platzieren, irgendwo ist es für andere leichter zu finden, lings Kommentar zu der obigen Antwort von jur .
df_diff = pd.concat([df1,df2]).drop_duplicates(keep=False)
Testen mit diesen Datenrahmen:
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'], })
Ergebnisse in diesem:
quelle
Aufbauend auf der Antwort von alko, die fast für mich funktioniert hat, mit Ausnahme des Filterungsschritts (wo ich :) bekomme
ValueError: cannot reindex from a duplicate axis
, ist hier die endgültige Lösung, die ich verwendet habe:# 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]
quelle
IndexError: index out of bounds'
, wenn ich versuche, die dritte Zeile auszuführen.# 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']
quelle
Es gibt eine einfachere Lösung, die schneller und besser ist, und wenn die Zahlen unterschiedlich sind, können Sie sogar Mengenunterschiede feststellen:
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_'])
Hier ist df_diff eine Zusammenfassung der Unterschiede. Sie können es sogar verwenden, um die Mengenunterschiede zu ermitteln. In Ihrem Beispiel:
Erläuterung: Um zwei Listen effizient zu vergleichen, sollten wir sie zuerst ordnen und dann vergleichen (die Konvertierung der Liste in Sets / Hashing wäre ebenfalls schnell; beide sind eine unglaubliche Verbesserung der einfachen O (N ^ 2) -Doppelvergleichsschleife
Hinweis: Der folgende Code erzeugt die Tabellen:
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'], })
quelle
Gründer hier eine einfache Lösung:
https://stackoverflow.com/a/47132808/9656339
pd.concat([df1, df2]).loc[df1.index.symmetric_difference(df2.index)]
quelle
# 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
quelle
Ich habe diese Lösung. Hilft dir das?
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))
Ergebnis
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
quelle
Da haben
pandas >= 1.1.0
wirDataFrame.compare
undSeries.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
quelle
Ein wichtiges Detail, das Sie beachten sollten, ist, dass Ihre Daten doppelte Indexwerte aufweisen . Um einen einfachen Vergleich durchführen zu können, müssen wir alles als eindeutig festlegen
df.reset_index()
und können daher eine Auswahl basierend auf den Bedingungen durchführen. Sobald in Ihrem Fall der Index definiert ist, gehe ich davon aus, dass Sie den Index beibehalten möchten, damit es eine einzeilige Lösung gibt:[~df2.reset_index().isin(df1.reset_index())].dropna().set_index('Date')
Sobald das Ziel aus pythonischer Sicht darin besteht, die Lesbarkeit zu verbessern, können wir ein wenig brechen:
# 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)
quelle
Hoffe das wäre nützlich für dich. ^ 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 """
quelle
Ich habe diese Methode ausprobiert und sie hat funktioniert. Ich hoffe es kann auch helfen:
"""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']]
quelle