Seite 1 von 1

Python Excel Vergleich Werte

Verfasst: Montag 12. Juli 2021, 17:38
von servus_97
Hi Leute,

ich würde euch gerne die Fragestellung erklären und hoffe auf einige Ansätze 😅

Fragestellung:
Ich muss eine Excel-Datei einlesen und dann die Werte einer Spalte vergleichen.
Zum Beispiel:
-Ich lese die Spalte "Marken" ein. Beim einlesen der Marken kommt es vor, dass anstatt "Nike" wir "Nik e" oder "Nik" steht. Meine Aufgabe ist es, dass das Programm trotzdem "Nike" erkennt und den String von "Nik" zu "Nike" ändert.

(Ich hoffe, dass ich das Problem verständlich erklären konnte)



Ich habe mir die Methode "replace()" angeschaut, jedoch macht es hier keinen Sinn. Da ich bspw. auch den Fall haben könnte:

- Wir haben als Input "B0sch AG" und in der Liste haben wir "bosch ag" und "bosch ag gmbh" und das Programm entscheidet sich für letzteres. Dann würde ein replace vieles verfälschen.

Bin etwas verzweifelt :(

LG

Re: Python Excel Vergleich Werte

Verfasst: Montag 12. Juli 2021, 18:01
von Sirius3
Welches Programm? Was hast Du versucht? Nach welchen Regeln soll denn die Ersetzung erfolgen?

Re: Python Excel Vergleich Werte

Verfasst: Montag 12. Juli 2021, 19:41
von LukeNukem
servus_97 hat geschrieben: Montag 12. Juli 2021, 17:38 Ich muss eine Excel-Datei einlesen und dann die Werte einer Spalte vergleichen.

-Ich lese die Spalte "Marken" ein. Beim einlesen der Marken kommt es vor, dass anstatt "Nike" wir "Nik e" oder "Nik" steht. Meine Aufgabe ist es, dass das Programm trotzdem "Nike" erkennt und den String von "Nik" zu "Nike" ändert.

- Wir haben als Input "B0sch AG" und in der Liste haben wir "bosch ag" und "bosch ag gmbh" und das Programm entscheidet sich für letzteres. Dann würde ein replace vieles verfälschen.
Das, was Du da beschreibst, läuft im Endeffekt auf einen unscharfen Zeichenkettenvergleich hinaus. Das Thema ist nicht ganz trivial, aber es gibt zum Glück mehrere Lösungsansätze.

Einer dieser Lösungsansätze könnte sein, eine entsprechende Funktion zu benutzen, die die Ähnlichkeit zwischen zwei Zeichenketten berechnet. Die Levenshtein- und die Damerau-Levenshtein-Distanz sind dazu sehr beliebt, siehe dazu [1]. Das ist recht einfach zu programmieren, denn dafür gibt es entsprechende Python-Bibliotheken, aber die Verarbeitung kann in Abhängigkeit von der Datenmenge relativ rechen- und zeitaufwändig werden.

Eine andere Alternative könnte es sein, die gewünschten korrekten Namen in eine Suchmaschine wie Pythons "Woosh"- [2] zu füttern und Deine Einträge einfach darin zu suchen. Das kann ganz gut funktionieren, aber ich habe damit keine eigenen Erfahrungen und kann daher nicht viel dazu sagen -- vielleicht weiß jemand anders hier ja mehr.

Ein dritter Ansatz und vermutlich der, mit dem ich persönlich anfangen würde, wäre es, einen einfachen, schnellen MachineLearning-Klassifizierer wie den NaiveBayesClassifier [3] aus dem Python-Paket NLTK mit entsprechend aufbereiteten Daten (N-Gramme auf Buchstaben?) zu trainieren und Deine Einträge dann davon klassifizieren zu lassen. Sowas ist auch für größere Datenmengen sehr schnell und im Kern auch recht leicht zu implementieren. Zudem können mit der Methore "prob_classify()" des NaiveBayesClassifier auch Wahrscheinlichkeiten für die gefundenen Treffer zurückgegeben werden. Dadurch könnest Du das Originalfeld zunächst behalten, in Deinen Pandas-DataFrame zwei neue Spalten mit der gefundenen Klasse ("Bosch AG") und der Trefferwahrscheinlichkeit hinzufügen, und dann die Treffer mit der geringsten Wahrscheinlichkeit noch einmal manuell prüfen. Als Klassen würde ich direkt die gesuchten Namen benutzen, als Features bei diesen kurzen Textfetzen bieten sich n-Gramme [4] (Unigramme, Bigramme und Trigramme) aus Buchstaben an. Nach meinen Erfahrungen funktioniert so etwas erstaunlich gut.

Ganz grundsätzlich wäre es allerdings womöglich sinnvoller, direkt an der Datenquelle für eine bessere Datenqualität zu sorgen... ;-)

[1] https://de.wikipedia.org/wiki/Levenshtein-Distanz
[2] https://whoosh.readthedocs.io/en/latest/intro.html
[3] https://www.nltk.org/book/ch06.html
[4] http://textmining.wp.hs-hannover.de/Spr ... mmung.html

Re: Python Excel Vergleich Werte

Verfasst: Montag 12. Juli 2021, 19:52
von servus_97
Wow :D Danke dir für die Ansätze.
Der dritte Ansatz spricht mich auch am ehesten an.

Re: Python Excel Vergleich Werte

Verfasst: Montag 12. Juli 2021, 20:18
von LukeNukem
servus_97 hat geschrieben: Montag 12. Juli 2021, 19:52 Wow :D Danke dir für die Ansätze.
Der dritte Ansatz spricht mich auch am ehesten an.
Cool, das freut mich.. und wenn Du am Ende vielleicht kurz etwas dazu sagen magst, ob und wie gut es funktioniert hat, freut es mich noch mehr! ;-)

Re: Python Excel Vergleich Werte

Verfasst: Dienstag 13. Juli 2021, 09:42
von servus_97
Okay, muss gestehen, dass es doch etwas komplizierter ist als ich gedacht habe.

Jetzt habe ich, wie in [4] die Spaltenwerte in n-gramme aufgeteilt über die Funktion xgram. Diese Werte würde ich dann als "feature_probdist" in der Klasse NaiveBayesClassifier verwenden und die einzelnen Markennamen aus der Spalte dann als "Label_probdist"

Mir stellen sich da echt viele Fragen 😅😅

Dann wüsste ich auch nicht, worauf ich die Methode "prob_classify()" anwenden soll.

Wäre echt sehr lieb, wenn du mir da ein wenig helfen könntest. Hab mir echt einiges angeschaut.

LG

Re: Python Excel Vergleich Werte

Verfasst: Dienstag 13. Juli 2021, 10:50
von servus_97
Würde ich jedoch den ersten Ansatz nehmen, so könnte man auch "nltk.edit_distance()" verwenden.
Hierfür würde ich einfach ein Duplikat von dem eigentlichen Datensatz erstellen, mit einigen Fehlern und die Spalte mit den Marken beider Datensätze in die Methode eingeben.

Bspw.:
data1 = Echte Datensatz --> Spalte s1
data2 = Fehler Datensatz --> Spalte s2

=> nltk.edit_distance(s1,s2) ?

Re: Python Excel Vergleich Werte

Verfasst: Dienstag 13. Juli 2021, 13:51
von LukeNukem
servus_97 hat geschrieben: Dienstag 13. Juli 2021, 09:42 Mir stellen sich da echt viele Fragen 😅😅
Frag' ruhig. ;-)
servus_97 hat geschrieben: Dienstag 13. Juli 2021, 09:42 Wäre echt sehr lieb, wenn du mir da ein wenig helfen könntest. Hab mir echt einiges angeschaut.
Also, die von Dir genannten korrekten Namen stehen bei mir zeilenweise in der "correct.txt", die defekten Namen genauso in der "failure.txt".

Code: Alles auswählen

#!/usr/bin/env python
FILE_CORRECT = 'correct.txt'
FILE_FAILURE = 'failure.txt'

from collections import defaultdict

import nltk


def ngrams(text, n):
    liste = []
    if n < len(text):
        for p in range(len(text) - n + 1) :
            tg = text[p:p+n]
            liste.append(tg)
    return liste


def xgrams(text, maxlen=3):
    return [w for n in range(1, maxlen+1) for w in ngrams(text.lower(), n)]


def extract_features(text):
    rv = defaultdict(lambda: 0)
    for w in xgrams(text.lower()): rv[w] += 1
    return dict(rv)
    

if __name__ == '__main__':
    with open(FILE_CORRECT, 'r') as ifh: data_correct = ifh.read().splitlines()
    with open(FILE_FAILURE, 'r') as ifh: data_failure = ifh.read().splitlines()
    
    classifier = nltk.NaiveBayesClassifier.train([(extract_features(line), line) for line in data_correct])
    for line in data_failure:
        classified = classifier.classify(extract_features(line))
        probdist = classifier.prob_classify(extract_features(line))
        print('{:10s} | {:0.2f} | {}'.format(classified, probdist.prob(classified), line))
Ausgabe bei mir:

Code: Alles auswählen

Nike       | 1.00 | Nik e
Nike       | 1.00 | Nik
Bosch AG   | 1.00 | bosch ag
Bosch AG   | 1.00 | bosch ag gmbh
Bosch AG   | 1.00 | B0sch AG
Also ich würde sagen: funktioniert prima.

Re: Python Excel Vergleich Werte

Verfasst: Dienstag 13. Juli 2021, 16:44
von servus_97
DANKEEEEEEEEEE :D
Ich gehe dein Code später durch und bei fragen komme ich auf dich zurück. Bist mein HELD ! ✌️

Re: Python Excel Vergleich Werte

Verfasst: Dienstag 13. Juli 2021, 20:04
von LukeNukem
servus_97 hat geschrieben: Dienstag 13. Juli 2021, 16:44 DANKEEEEEEEEEE :D
Ich gehe dein Code später durch und bei fragen komme ich auf dich zurück. Bist mein HELD ! ✌️
Oh, dankeschön, aber... da nicht für, sehr gerne. Eigentlich ist das gar nicht schwierig, wenn man das einmal gemacht hat, und je nachdem, wie man seine Features aufbereitet, ist es auch ziemlich vielseitig nutzbar. Hoffentlich funktioniert es auch auf Deinen übrigen Daten so gut, viel Spaß und Erfolg damit! ;-)

Re: Python Excel Vergleich Werte

Verfasst: Mittwoch 14. Juli 2021, 00:35
von rogerb
@LukeNukem,

schönes Beispiel, hätte nicht gedacht, dass das so einfach ist.
Bisher hatte ich mich ehrlich gesagt nicht sonderlich für ML interessiert.
Bei kurzen Worten merkt man schon wie es ungenauer mit der Erkennung wird.
Für einen OCR-Text sollte das aber schon eine Menge bringen.

Man kann sich die n-grams anscheinend auch sehr gut vom NLTK als Tuple erstellen lassen:

Code: Alles auswählen

#!/usr/bin/env python
from collections import defaultdict

import nltk
from nltk.util import ngrams


FILE_CORRECT = "correct.txt"
FILE_FAILURE = "failure.txt"


def extract_features(text):
    features = defaultdict(int)
    for count in range(1, 4):
        for ngram in ngrams(text, count):
            features[ngram] += 1
    return features


if __name__ == "__main__":
    with open(FILE_CORRECT, "r") as text_file:
        data_correct = text_file.read().splitlines()
    with open(FILE_FAILURE, "r") as text_file:
        data_failure = text_file.read().splitlines()

    classifier = nltk.NaiveBayesClassifier.train(
        ((extract_features(line.lower()), line) for line in data_correct)
    )
    for line in data_failure:
        classified = classifier.classify(extract_features(line))
        probdist = classifier.prob_classify(extract_features(line))
        print(f"{classified:10s} | {probdist.prob(classified):0.2f} | {line}")

Re: Python Excel Vergleich Werte

Verfasst: Samstag 17. Juli 2021, 10:54
von LukeNukem
rogerb hat geschrieben: Mittwoch 14. Juli 2021, 00:35 schönes Beispiel, hätte nicht gedacht, dass das so einfach ist.
Bisher hatte ich mich ehrlich gesagt nicht sonderlich für ML interessiert.
Naja, sagen wir so: ich hab's einfach gemacht. Man kann da schon wesentlich mehr Arbeit hineinstecken... Der größte Aufwand ist meist, verschiedene Kombinationen von Datenaufbereitung, Merkmalsextraktion und ML-Algorithmen mit randomisierten Trainingsdaten zu füttern und zu schauen, wie gut diese Kombinationen dann jeweils funktionieren...
rogerb hat geschrieben: Mittwoch 14. Juli 2021, 00:35 Bei kurzen Worten merkt man schon wie es ungenauer mit der Erkennung wird.
Naja, Garbage in, Garbage out... Ich mein', so ein Zeichen hat ja nur einen sehr begrenzten Informationsgehalt, und wenn die Zeichenkette kurz genug ist... dann ist halt naturgemäß wenig Information drin. Man kann die Ergebnisse sehr deutlich beeinflussen, je nachdem, wie man die Merkmale konstruiert, wie groß die Trainingsdaten sind, und welchen Algorithmus man wählt. Naive Bayes ist eben einer der bekanntesten und performantesten, aber im Kern ziemlich einfach und nicht für alle Anwendungsfälle geeignet. Und das von mir gezeigte ist ja auch alles andere als ein typischer Anwendungsfall, ganz im Gegenteil ist diese Art der Nutzung durchaus ein bisschen... kreativ, diplomatisch gesagt. Aber für den Fall des TO und die von ihm genannten Beispieldaten funktioniert der Ansatz ziemlich gut, würde ich sagen. ;-)
rogerb hat geschrieben: Mittwoch 14. Juli 2021, 00:35 Für einen OCR-Text sollte das aber schon eine Menge bringen.
Probier's halt aus... obwohl, in dem Fall würde ich es vermutlich eher erst einmal mit Bag-Of-Words, Wort-Ngrammen und Wörterbüchern anfangen. Durch die Accuracy-Funktion von NLTK lassen sich die Ergebnisse zum Glück recht einfach überprüfen.
rogerb hat geschrieben: Mittwoch 14. Juli 2021, 00:35 Man kann sich die n-grams anscheinend auch sehr gut vom NLTK als Tuple erstellen lassen:
Die hab' ich vor einigen Jahren mal ausprobiert, und sie war mir damals leider zu langsam. Keine Ahnung, ob das immer noch so ist... muß ich mir wohl mal wieder angucken... ;-)

Re: Python Excel Vergleich Werte

Verfasst: Samstag 17. Juli 2021, 16:59
von servus_97
Hi Leute,

habe erst heute Zeit gefunden mir es ein wenig genauer anzuschauen :) Danke euch.

Also die Excel Dateien die ich einlesen will und deren Spalten ich dann Vergleiche haben jeweils 5 Spalten.

Ich habe zuerst die Excel Dateien über

Code: Alles auswählen

pd.read_excel()
eingelesen.

Danach habe ich

Code: Alles auswählen

FILE_CORRECT =df1['Name'] 
FILE_FAILURE= df2['Name'] 
und den Part des Codes

Code: Alles auswählen

if __name__ == "__main__":
    with open(FILE_CORRECT, "r") as text_file:
        data_correct = text_file.read().splitlines()
    with open(FILE_FAILURE, "r") as text_file:
        data_failure = text_file.read().splitlines()
weggelassen.

Und bekomme nun den Fehler
AttributeError: 'float' object has no attribute 'lower'

Re: Python Excel Vergleich Werte

Verfasst: Samstag 17. Juli 2021, 17:48
von servus_97
Was ich halt nicht verstehe, woher dieses float object kommt. Das sollten doch eigentlich strings sein :roll:

Re: Python Excel Vergleich Werte

Verfasst: Samstag 17. Juli 2021, 17:50
von __deets__
Pandas konvertiert Datentypen.

Re: Python Excel Vergleich Werte

Verfasst: Samstag 17. Juli 2021, 18:01
von servus_97
Also schlägst du vor mit einer anderen Bibliothek die Daten einzulesen ?

Wie bspw. openpyxl

Re: Python Excel Vergleich Werte

Verfasst: Samstag 17. Juli 2021, 18:02
von servus_97
Also schlägst du vor mit einer anderen Bibliothek die Daten einzulesen ?

Wie bspw. openpyxl

Re: Python Excel Vergleich Werte

Verfasst: Samstag 17. Juli 2021, 19:12
von nezzcarth
servus_97 hat geschrieben: Dienstag 13. Juli 2021, 10:50 Würde ich jedoch den ersten Ansatz nehmen, so könnte man auch "nltk.edit_distance()" verwenden.
Du hast dich jetzt schon für einen anderen Ansatz entschieden, wenn ich das korrekt verstanden habe, aber mal der Vollständigkeit halber:

'nltk.edit_distance' ist nur mit Einschränkung zu empfehlen. Das verwendet, soweit ich das sehe, die "Lehrbuchimplementierung" mit Dynamic Programming und ist in reinem Python geschrieben. Für kleine Mengen und zum Rumspielen ist das okay. Aber wenn Performance wichtig ist, würde ich das nicht empfehlen. In der Fachliteratur wurden diverse Verbesserungen der Zeichenkettendistanz beschrieben. Auf Pypi findet man eine handvoll Implementierungen, die in C, C++ und/oder Cython implementiert sind und zumindest teilweise einige dieser optimierten Algorithmen einsetzen. Wenn es um größere Datenmengen, d.h. viele Vergleiche geht, würde ich daher dort schauen und dann die Implementierung nehmen, die für dich am besten funktioniert.

Re: Python Excel Vergleich Werte

Verfasst: Sonntag 18. Juli 2021, 16:25
von servus_97
Habe es doch geschafft, indem ich einfach die zu betrachtende Spalte ausgewählt und dann habe ich einfach

Code: Alles auswählen

x = df_correct['name'].to_string().splitlines()
in eine Variable gespeichert. Auch für den zweiten Excel Sheet.

Jetzt hatte ich extra einige Buchstaben für Testzwecke entfernt und habe den Code abgespielt.

Jetzt bekommen ich überall
Nike | 1 | Ni
die Wahrscheinlichkeit 1.
D.h. der Algorithmus erkennt Ni mit 100% WK als Nike an ?

Und wie könnte ich jetzt einfach, in dem Fall, Ni als Nike ändern ?

Re: Python Excel Vergleich Werte

Verfasst: Dienstag 27. Juli 2021, 16:11
von LukeNukem
servus_97 hat geschrieben: Sonntag 18. Juli 2021, 16:25 Jetzt bekommen ich überall
Nike | 1 | Ni
die Wahrscheinlichkeit 1.
D.h. der Algorithmus erkennt Ni mit 100% WK als Nike an ?
...unter den gegebenen Auswahlmöglichkeiten, genau. Wenn Du meinen Code benutzt hast, sind das natürlich 100%, denn die Anzahl der korrekten Möglichkeiten ist mit 2 ja sehr überschaubar, und die beiden Namen "Nike" und "Bosch AG" unterscheiden sich ja dann doch sehr deutlich.
servus_97 hat geschrieben: Sonntag 18. Juli 2021, 16:25 Und wie könnte ich jetzt einfach, in dem Fall, Ni als Nike ändern ?
Ich würde dem DataFrame zu Kontrollzwecken zwei neue Spalten hinzufügen, so im Kern (ungetestet):

Code: Alles auswählen

def predict_name(val): 
    # Korrekten Namen 'name' und Wahrscheinlichkeit 'prob' berechnen
    return pd.Series({'name': name, 'prob': prob})

df[['name', 'prob']] = df.Marken.apply(predict_name, axis=1)
Danach würde ich mir die drei Spalten mal nebeneinander ausgeben lassen und das Ergebnis manuell überprüfen. HTH, have fun! ;-)