@vanKey: Der schleifenbasierte Code ist sehr ineffizient. Nicht weil er in Python-Schleifen geschrieben ist, sondern weil der Ansatz für jeden Eintrag aus der 1. Datei jeden Eintrag aus der 2. Datei zur durchsuchen. Wenn man das in Python-Code lösen wollen würde, dann würde man die zweite Datei in ein Wörterbuch einlesen, und dann im nächsten Schritt die erste Datei durcharbeiten und für jeden Eintrag den Wert für die zweite Spalte im Wörterbuch nachschlagen.
Numpy wird importiert, in dem Beispiel aber gar nicht verwendet.
Es ist nur ein generisches Beispiel, aber man nummeriert keine Namen. Das betrifft auch die Spaltennamen. Ich würde auch in Beispielen versuchen das zu vermeiden, sonst gewöhnt man sich das auch in Produktivcode eher an.
`data_file_*` ist als Name für einen `DataFrame` irreführend. Bei `*_file` erwartet der Leser ein Objekt das eine Datei repräsentiert und mindestens eine `read()`- oder eine `write()`-Methode, und in der Regel eine `close()`-Methode besitzt. Hinter den Namen verbergen sich nicht die Dateien, sondern deren Inhalt(e).
Kommmentare werden mit einem "#" eingeleitet. Da braucht man keine drei.
0 ist der Default-Startwert von `range()`, den braucht man nicht angeben.
Man macht auch in Python in der Regel etwas falsches oder zumindest komisches wenn man über einen Laufindex iteriert, der dann nur verwendet wird um über die Elemente von einer Sequenz zu iterieren. Man kann in Python *direkt* über die Elemente iterieren, ohne den Umweg über einen Laufindex. ``for i in range(len(sequence)):`` ist in Python ein „anti pattern“. Falls man zusätzlich zu den Elementen noch eine laufende ganze Zahl benötigt, gibt es die `enumerate()`-Funktion. Im konkreten Fall haben wir ein `Series`-Objekt das eine Methode bietet um über Index/Wert-Paare zu iterieren. Der Index von einem `DataFrame` muss ja nicht aus fortlaufenden Nummern mit 0 beginnend bestehen.
Der ursprüngliche, schleifenbasierte Code könnte dann so aussehen:
Code: Alles auswählen
#!/usr/bin/env python3
import pandas as pd
def main():
data_a, data_b = (
pd.read_csv(
filename, delim_whitespace=True, header=None, names=["ID", "Wert"]
)
for filename in ["file_1.txt", "file_2.txt"]
)
print(data_a)
print(data_b)
for index, wanted_id in data_a["ID"].iteritems():
for id_, value in data_b.itertuples(False):
if wanted_id == id_:
data_a.at[index, "Wert"] = value
print(data_a)
if __name__ == "__main__":
main()
Eine effiziente Lösung ohne Pandas um die Werte den IDs zuzuordnen könnte so aussehen:
Code: Alles auswählen
#!/usr/bin/env python3
import math
def main():
with open("file_2.txt", encoding="ascii") as lines:
id_to_value = dict(tuple(map(int, line.split())) for line in lines)
with open("file_1.txt", encoding="ascii") as lines:
for id_ in map(int, lines):
print(f"ID: {id_}, Wert: {id_to_value.get(id_, math.nan)}")
if __name__ == "__main__":
main()
Mit Pandas würde es sich auch anbieten die IDs tatsächlich als Index vom `DataFrame` zu verwenden, dann kann man statt `merge()`, `join()` verwenden:
Code: Alles auswählen
#!/usr/bin/env python3
import pandas as pd
def main():
data_a, data_b = (
pd.read_csv(
filename,
delim_whitespace=True,
header=None,
names=column_names,
index_col="ID",
)
for filename, column_names in [
("file_1.txt", ["ID"]),
("file_2.txt", ["ID", "Wert"]),
]
)
print(data_a)
print(data_b)
print(data_a.join(data_b))
if __name__ == "__main__":
main()