Geschätzte Lesezeit: 5 Minuten
In unserem vorherigen Beitrag über den Vergleich von CSV-Dateien auf Unterschiede haben wir gezeigt, wie Sie die Unterschiede sehen können. Was aber, wenn Sie sehen möchten, ob ein Datensatz zu 100 % übereinstimmt oder nicht?
Hier werden wir SequenceMatcher verwenden, eine Python-Klasse, mit der Sie Dateien vergleichen und eine prozentuale Übereinstimmung zurückgeben können.
Schauen wir uns den Code an
Importieren Sie Anweisungen und lesen Sie die CSV-Dateien ein. Hier importieren wir wie üblich die benötigten Bibliotheken und lesen die beiden CSV-Dateien ein, die wir verwenden:
Beachten Sie, dass wir hier auch die Einstellungen für den Datenrahmen festlegen, damit wir den Datenrahmen richtig sehen können. Siehe weiter unten.
import pandas as pd
import numpy as np
import math
from difflib import SequenceMatcher
pd.set_option('max_columns', None)
pd.set_option('display.width', None)
#Read in the CSV files
df1 = pd.read_csv('CSV1.csv')
df2 = pd.read_csv('CSV2.csv')
Die beiden CSV-Dateien sehen wie folgt aus:
CSV1
CSV2
Als Nächstes werden wir ein Array erstellen. Durch die Erstellung eines Arrays kann der Vergleich abgeschlossen werden, da Indizes erstellt werden, und die Indizes in jedem Array können verglichen und dann die prozentuale Differenz berechnet werden.
#Create an array for both dataframes
array1 = np.array(df1)
array2 = np.array(df2)
Unser nächster Schritt besteht darin, die Arrays in einen Datenrahmen zu übertragen, alle Integer-Werte in eine Zeichenkette zu ändern und dann beide Datenrahmen zu einem zusammenzufügen.
In diesem Fall ermöglicht die Umwandlung der Werte in eine Zeichenkette, dass über diese Werte iteriert werden kann, andernfalls wird der Fehler " TypeError: 'int' object is not iterable" angezeigt.
#Transfer the arrays to a dataframe
df_CSV_1 = pd.DataFrame(array1, columns=['No1','Film1','Year1','Length1'])
df_CSV_2 = pd.DataFrame(array2, columns=['No2','Film2','Year2','Length2'])
#Change all the values to a string, as numbers cannot be iterated over.
df_CSV_1['Year1'] = df_CSV_1['Year1'].astype('str')
df_CSV_2['Year2'] = df_CSV_2['Year2'].astype('str')
df_CSV_1['Length1'] = df_CSV_1['Length1'].astype('str')
df_CSV_2['Length2'] = df_CSV_2['Length2'].astype('str')
#join the dataframes
df = pd.concat([df_CSV_1,df_CSV_2], axis=1)
Wir gehen jetzt zum Hauptteil des Programms über, der uns die Antworten liefert, die wir brauchen. Hier erstellen wir eine Funktion, die die Berechnungen für uns durchführt:
#Create a function to calculate the differences and show as a ratio.
def create_ratio(df, columna, columnb):
return SequenceMatcher(None,df[columna],df[columnb]).ratio()
Als nächstes berechnen wir die Differenzen und formatieren die Ausgabe
#Here we use apply which will pull in the data that needs to be passed to the fuction above.
df['Film_comp'] = df.apply(create_ratio,args=('Film1','Film2'),axis=1)
df['Year_comp'] = df.apply(create_ratio,args=('Year1','Year2'),axis=1)
df['Length_comp'] = df.apply(create_ratio,args=('Length1','Length2'),axis=1)
#This creates the values we are looking for
df['Film_comp'] = round(df['Film_comp'].astype('float'),2)*100
df['Year_comp'] = round(df['Year_comp'].astype('float'),2)*100
df['Length_comp'] = round(df['Length_comp'].astype('float'),2)*100
#this removes the decimal point that is added as a result of using the datatype 'Float'
df['Film_comp'] = df['Film_comp'].astype('int')
df['Year_comp'] = df['Year_comp'].astype('int')
df['Length_comp'] = df['Length_comp'].astype('int')
#Print the output
print(df)
Und die endgültige Ausgabe sieht so aus:
Eine Erläuterung der Ausgabe
Wie man sieht, sind die letzten drei Spalten die Prozentsätze der erzielten Übereinstimmung, wobei 100 eine exakte Übereinstimmung bedeutet.
Für den Indexwert 1 gibt es Joker in der ersten Datei, aber Jokers ist in der zweiten Datei.
Das Verhältnis wird wie folgt berechnet:
Joker ist Länge 5, Joker ist Länge 6 = 11 Zeichen lang
Die Logik sieht sich also die Sequenz an, iteriert durch die Sequenz und stellt fest, dass die ersten 10 Zeichen in der gleichen Reihenfolge sind, aber das 11:
(10/11) * 100 = 90.90
Schließlich setzt die Rundungsfunktion den gesuchten Wert auf 91.
Auf der gleichen Linie werden wir das Jahr vergleichen:
2019 und 2008 bestehen aus insgesamt acht Zeichen.
In der Reihenfolge stimmen die ersten beiden überein, und da sie auch gefunden werden, ergeben sich vier, und das Verhältnis ist wie folgt:
4/8 *100 = 50
Für Index 20 haben wir auch den Filmnamen verglichen, insgesamt sind es 17 Zeichen, aber das Programm ignoriert das, was es Junk nennt, also das Leerzeichen wird nicht mitgerechnet, deshalb wird das Verhältnis erst ab 16 Zeichen berechnet.
Um dies besser verstehen zu können, habe ich die folgenden Informationen zusammengestellt:
Index 1 | Index 1 | ||||||
2019 | 2008 | 8 | Joker | Joker | 11 | ||
2 | Korrekter Punkt | 1 | J | Korrekter Punkt | 1 | ||
0 | Korrekter Punkt | 1 | o | Korrekter Punkt | 1 | ||
1 | Falsche Stelle | 0 | K | Korrekter Punkt | 1 | ||
9 | Falsche Stelle | 0 | e | Korrekter Punkt | 1 | ||
r | Korrekter Punkt | 1 | |||||
2 | Gefunden | 1 | J | Gefunden | 1 | ||
0 | Gefunden | 1 | o | Gefunden | 1 | ||
1 | Gefunden | 0 | K | Gefunden | 1 | ||
9 | Gefunden | 0 | e | Gefunden | 1 | ||
r | Gefunden | 1 | |||||
Insgesamt im Vergleich | 8 | Insgesamt im Vergleich | 11 | ||||
Ratio | 0.50 | Ratio | 0.91 | ||||
Index 20 | |||||||
Der Dreck | Die Schmutzige | 16 | |||||
T | Korrekter Punkt | 1 | |||||
H | Korrekter Punkt | 1 | |||||
E | Korrekter Punkt | 1 | |||||
Korrekter Punkt | 1 | ||||||
T | Gefunden | 1 | |||||
H | Gefunden | 1 | |||||
E | Gefunden | 1 | |||||
D | Korrekter Punkt | 1 | |||||
I | Korrekter Punkt | 1 | |||||
R | Korrekter Punkt | 1 | |||||
T | Korrekter Punkt | 1 | |||||
D | Gefunden | 1 | |||||
I | Gefunden | 1 | |||||
R | Gefunden | 1 | |||||
T | Gefunden | 1 | |||||
Insgesamt im Vergleich | 16 | ||||||
Ratio | 0.94 |