Python Skript funktioniert nicht?
Hi,
ich habe zwei .csv Dateien mit folgenden Spalten.
csv1:
csv2:
Ich möchte immer dann wenn die Spalten A-D identisch sind die ID2 aus csv2 in Spalte F in csv1 schreiben. Bisher habe ich folgenden Code:
for row in csv1:
for line in csv2:
print(row[0])
print(row[1])
if row[0] == line[0] and row[1] == line[1] and row[2] == line[2] and row[3] == line[3]:
row[5] = line[4]
print(row[5])
Die Idee ist: Ich fange bei einer Zeile in csv1 an, Prüfe diese Zeile mit jeder Zeile in csv2 und wenn die Spalten den gleichen Wert haben, schreibe den Wert von ID2 in die nächste Spalte von csv1.
Mein Ergebnis ist:
Ich habe erwartet, dass
Nachname
Vorname
ganz oft ausgegeben wird, aber zum Schluss die ID2 und danach die tatsächlichen Nachnamen und Vornamen aus csv1. Die Print Befehle sind jetzt erstmal nur dazu da um zu verstehen was passiert. Es scheint so zu sein, dass nach dem Durchlauf der zweiten For-Schleife auch die erste Schleife beendet wird. Woran liegt das?
Ich hoffe die Frage ist klar geworden, es ist spät, heiß und ich bin schon müde. Ich freue mich über Antworten. Wenn nicht sehe ich zu, dass ich die Frage morgen nochmal besser schreibe.
Grüße
3 Antworten
Deine Logik ist natürlich sehr ineffizient, schaut aber erstmal richtig aus. Wenn die CSVs nicht allzu groß sind, musst du dir kein effizienteres Vorgehen ausdenken. (Es wäre trotzdem eine gute Übung...)
Was genau sind "csv1" und "csv2"? Deiner Logik nach sollten es wohl Listen von Listen sein, die jeweils die Felder der CSVs enthalten. Erste Dimension die Zeile, zweite Dimension das Feld.
Ist das wirklich so? Ich hätte sonst einen vagen Verdacht, dass du direkt ein "Reader Object" verwendest, also einen Iterator - und der wird nur ein einziges Mal drüberiterieren können.
Sind die Daten gesäubert wo nötig, d.h. musst du vielleicht .trim() verwenden, um unnötige Leerzeichen loszuwerden?
if row[0] == line[0] and row[1] == line[1] and row[2] == line[2] and row[3] == line[3]:
Das ist nicht falsch, ginge aber auch einfacher - mit dem angenehmen Nebeneffekt, dass man sich weniger leicht vertippt:
if row[:4] == line[:4]:
Ich habe tatsächlich Reader verwendet und habe den Teil des Codes nicht in die Frage geschrieben weil ich versuche die Fragen immer so kurz aber nötig wie möglich zu stellen. Mir war nicht klar, dass ich den Reader nur einmal verwenden kann. Ich erzeuge jetzt den Reader für die zweite Datei innerhalb der ersten for-Schleife, sodass er immer wieder auf's neue erzeugt wird. Damit funktioniert der Code nun. Danke für die Hilfe und Tipps
Das mit dem ReadeObject ist definitiv ein guter Hinweis, habe ich gar nicht dran gedacht.
Wieviele Zeilen sind in csv1 und csv2 jeweils enthalten?
Die Ausgabe müsste doch mit "Vorname" beginnen, weil das die erste Spalte (mit Index 0) ist. Kann es sein, dass er einfach hochgescrollt hat und die richtige Ausgabe nicht zu sehen ist?
Die Idee ansich sollte funktionieren, sehr viel besser wäre es aber die kleinere Datei zu Hashen und dann die andere Datei abzuarbeiten und das Hash zu nutzen.
row[5] = line[4]
Hier würde ich im Zweifelsfall eine Exception erwarten, weil es den Index noch nicht gibt (oder doch? Warum?).
Das keien Exception geworfen wird, könnte dann eben bedeuten, daß Deine Bedingung nie wahr wird.
Im Endeffekt kannst Du Dir anschauen, wie RDBMSes einen Hash-Join umsetzen.
Exemplarisch:
d=dict()
for t in csv1:
d["".join(t[:4])]=t
#Listen sind nicht hashbar, kann man auch schöner machen.
#z.B. die Felder vorher trimmen und in lowercase konv.
for t in csv2:
if "".join(t[:4]) in d:
#unsere ersten 4 Felder matchen
#Jetzt je nach Bedarf Daten zusammenführen
# wegschreiben.
So iterierst Du nur einmal über beide Dateien und bist schon fertig. Zumindest solange mindestens die kleinere Datei leicht komplett in den RAM passt.
Hi,
ich habe mir leider erst jetzt die Zeit genommen, mir deinen Vorschlag mit dem Dictionary in Ruhe anzusehen und zu verstehen. Musste mich erstmal mit Dictionary und Hashing auseinander setzten... Finde deinen Vorschlag sehr cool und habe jetzt wieder etwas neues dazu gelernt. Auf alle Fälle leichter und effizienter, als über zwei verschachtelte For-Schleifen zu gehen. Danke dir!
Grüße
das muss ich mir bei Gelegenheit mal überlegen, wie das funktioniert. Habs jetzt mit meinem ineffizienten Code hinbekommen, aber man will ja dazu lernen. Danke für den Input