Hallo Python Experte!
ich mache gerade mein Praktikum und habe erst seit kurzem angefangen Python zu lernen.
Letzte Woche hatte ich schön die erste Aufgabe von meinem Betreue bekommen und stehe einbißchen unter Druck und Stress.
Vielleicht könnte mir jemand helfen
Mein Problem ist folgendes.
Ich habe 2 CSV-Dateien "report1 und report2" (siehe unten)
und möchte mal ein Progamm schreiben, das Daten aus den 2 Dateien "report1 und report2" einliest und
in einem dritten Datei namens "report" (siehe unten)schreibt. Die Datei "report" soll wie im Anhang aussehen.
Ich habe schön ein Programm geschrieben, mit dem man aus dem Datei "report" die einzelnen Werten von "report1 und report2" einliest und
daraus den Mittelwert berechnet. Mein größte Problem ist jetzt wie mann aus den 2 Dateien "report1 und report2", die Datei "report" bekomme.
ich würde mich sehr freuen, wenn mir jemand helfe könnte, Da ich schon nächste Woche etwa an meinem Betreue präsentieren werde.
Danke im voraus und viele Grüße
Datei "report1.csv" (7 Zeilen und 2 Spalten)
name kmstand
Daniel 29
David 10
Sebastian 30
Jan 7
Lucas 120
Patrick 45
Datei "report2.csv" (8 Zeilen und 2 Spalten)
name kmstand
Daniel
David 24
Sebastian 10
Jan
Lucas 50
Patrick 20
Emil 40
Datei "report.csv" (3 Zeilen und 8 Spalten wobei die erste Zelle der ersten Spalten bzw Zeile frei ist)
Daniel David Sebastian Jan Lucas Patrick Emil
report1 29 10 30 7 120 45
report2 24 10 50 20 40
2 CSV-Dateien kombinieren
@fred1901: Die Aufgabe ist scheint mir nicht klar genug definiert zu sein. Du schreibst zum Beispiel bei Report 1 es wären sieben Zeilen, ich komme beim Zählen aber auf 8. Oder zählt die Leerzeile nach der "Titelzeile" nicht mit? Ist die in der Datei vorhanden? Was sind die Trennzeichen? Einzelne Leerzeichen? Wäre eher ungewöhnlich für das Dateiformat.
In der zweiten Datei sind nicht bei allen Namen auch Werte -- im Ergebnis tauchen dann aber welche auf!? Oder liegt das nur an der kaputten Formatierung!?
In der zweiten Datei sind nicht bei allen Namen auch Werte -- im Ergebnis tauchen dann aber welche auf!? Oder liegt das nur an der kaputten Formatierung!?
Hallo Leute und danke erst mal für Ihre schnelle Antwort.
Ich entschuldige mich, wenn ich nicht ganz klar war. Die Aufgabe wurde heute morgen umformuliert und ich hoffe jetzt etwa klarer zu sein.
++++++++++++++ Datei "report1"+++++++++++++++++
Die erste Spalte enthält folgende Einträge:
Daniel
Daniel
Daniel
Lucas
Lucas
Die zweite Spalte (String mit Zahlen, die durch leerzeichen getrennt sind) enthält folgende Einträge
"20 8 0"
"10 0 0"
"30 0 0"
"70 4 0"
"12 0 0"
++++++++++++++ Datei "report2"++++++++++++++++++++++++
Die erste Spalte enthält folgende Einträge:
David
Jan
Und die zweite Spalten folgende Einträge
"15 0 0"
"20 0 0"
Ich interessiere mich bei den String nur für die erste Zahlen ( z.B die Zahl 15 bei "15 0 0" soll eingelesen werden)
Es soll bei jedem Name jeweils die ersten Zahlen eingelesen und daraus den Mittelwert berechnet, der dann in die Datei "report" kommt ( z.B bei Daniel die drei mal vorkommt, den Mittelwert aus den 3 Zahlen berechnen)
Die Datei "report" soll so aussehen
Erste Spalte( fängte aber ab dem 2. Zelle) enthält folgende Einträge:
report1
report2
Zweite Spalte:
Daniel
Mittelwert aus den eingelesenen Zahlen von Daniel(dies sind 20 10 30)
Dritte Spalte:
Lucas
Mittelwert aus den eingelesenen Zahlen von Lucas(dies sind 70 12)
Vierte Spalte:
David
Mittelwert aus den eingelesenen Zahlen von David(dies ist 15)
fünfte Spalte:
Jan
Mittelwert aus den eingelesenen Zahlen von Jan(dies ist 20)
Trennzeichen ist der Strichpunkt ";"
Der folgende Code ist nur zum einlesen der berechnete Mittelwert aus der Datei "report" und noch daraus je nach report den Mittelwert zu berechnen.
Ich hätte auch den Name der Datei dem Konstruktor übergeben sollen aber ich weiss es nicht was am besten wäre, Da es noch weitere funktionen(z.B schreiben in der csv-Datei) in der Klasse kommen werden
Auch mit dem Privat attribut der Klasse. Ich glaube es wäre besser Sie so zu declarieren
self._report = list()
self._name = list()
Ich hoffe ich war nicht zu lang und auch, dass Sie die Aufgabe jetzt etwa besser verstehen werden.
Vielen Dank nochmals und viele Grüße
Fred
Ich entschuldige mich, wenn ich nicht ganz klar war. Die Aufgabe wurde heute morgen umformuliert und ich hoffe jetzt etwa klarer zu sein.
++++++++++++++ Datei "report1"+++++++++++++++++
Die erste Spalte enthält folgende Einträge:
Daniel
Daniel
Daniel
Lucas
Lucas
Die zweite Spalte (String mit Zahlen, die durch leerzeichen getrennt sind) enthält folgende Einträge
"20 8 0"
"10 0 0"
"30 0 0"
"70 4 0"
"12 0 0"
++++++++++++++ Datei "report2"++++++++++++++++++++++++
Die erste Spalte enthält folgende Einträge:
David
Jan
Und die zweite Spalten folgende Einträge
"15 0 0"
"20 0 0"
Ich interessiere mich bei den String nur für die erste Zahlen ( z.B die Zahl 15 bei "15 0 0" soll eingelesen werden)
Es soll bei jedem Name jeweils die ersten Zahlen eingelesen und daraus den Mittelwert berechnet, der dann in die Datei "report" kommt ( z.B bei Daniel die drei mal vorkommt, den Mittelwert aus den 3 Zahlen berechnen)
Die Datei "report" soll so aussehen
Erste Spalte( fängte aber ab dem 2. Zelle) enthält folgende Einträge:
report1
report2
Zweite Spalte:
Daniel
Mittelwert aus den eingelesenen Zahlen von Daniel(dies sind 20 10 30)
Dritte Spalte:
Lucas
Mittelwert aus den eingelesenen Zahlen von Lucas(dies sind 70 12)
Vierte Spalte:
David
Mittelwert aus den eingelesenen Zahlen von David(dies ist 15)
fünfte Spalte:
Jan
Mittelwert aus den eingelesenen Zahlen von Jan(dies ist 20)
Trennzeichen ist der Strichpunkt ";"
Der folgende Code ist nur zum einlesen der berechnete Mittelwert aus der Datei "report" und noch daraus je nach report den Mittelwert zu berechnen.
Code: Alles auswählen
# -*-coding:Latin-1 -*
import csv
import sys
class readInCSV(object):
def __init__(self):
self.report = list()
self.name = list()
def average(self, filename):
self.fileName = filename
try:
self.fileObj = open(self.fileName, "rb")
self.fileReader = csv.reader(self.fileObj, delimiter = ';')
except IOError:
print "Error --> can\'t find file or read data"
sys.exit()
report2name = dict()
for data in self.fileReader:
data = ",".join(data)
assignment = data.split(",", 1)
self.report .append(assignment[0])
self.name = [int(n) for n in assignment[1].split(',')]
report2name [assignment[0]] = self.name
for report, name in sorted( report2name .iteritems()):
print '%s: %.2f' % (report , float(sum(name )) / len(name))
self.fileObj.close()
Auch mit dem Privat attribut der Klasse. Ich glaube es wäre besser Sie so zu declarieren
self._report = list()
self._name = list()
Ich hoffe ich war nicht zu lang und auch, dass Sie die Aufgabe jetzt etwa besser verstehen werden.
Vielen Dank nochmals und viele Grüße
Fred
Zuletzt geändert von Anonymous am Donnerstag 14. April 2011, 15:22, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
Grund: Quelltext in Python-Code-Tags gesetzt.
Das ist irgendwie vermurkster Code mit zusätzlich unglücklicher Wahl der Bezeichnernamen. Eine Liste die name heißt, dann aber Integer-Werte enthält, kommt mir komisch vor. Ich sehe auch noch nicht den Grund, warum eine Klasse im Spiel ist. Alles in allem habe ich aufgehört zu versuchen zu verstehen was da passiert.
Ich möchte mal folgenden Ansatz ins Spiel bringen:
Eine Bitte: Verwende beim Einstellen von Code ins Forum bitte Python-Tags, sonst ist der Quelltext nicht gerade gut lesbar.
Ich möchte mal folgenden Ansatz ins Spiel bringen:
Code: Alles auswählen
import collections
import csv
database = collections.defaultdict(list)
report = csv.reader(open('csv_reader_02.csv'), delimiter=';')
for name, values in list(report):
database[name].append(int(values.split(' ')[0]))
print database
@fred1901: Das sieht alles ein wenig wirr aus und die Beschreibung der Ausgabeformats klingt so als wenn in der ersten Spalte zwar für jeden Report eine Zeile besteht, aber in allen anderen Spalten nur die ersten beiden Zeilen Werte enthalten.
Der Quelltext ist zu kompliziert. Insbesondere ist die Klasse unsinnig. Das erkennt man vielleicht auch schon am Namen, der bei Klassen übrigens mit einem Grossbuchstaben beginnen sollte. Klassen beschreiben "Dinge" während Funktionen und Methoden "Tätigkeiten" beschreiben. `readInCSV` ist keine Beschreibung für ein "Ding".
Attribute sollte man auch alle in der `__init__` definieren. Wenn bei Methodenaufrufen welche hinzukommen wird es schnell unübersichtlich und fehleranfällig. Zumal in `average()` auch Werte an das `readInCSV`-Exemplar gebunden werden, die eindeutig nur innerhalb der Methode von Interesse sind. Andererseits sehe ich keinen Sinn darin auf `self.report` und `self.name` zuzugreifen und damit wäre das einfach nur eine Funktion und keine Methode.
Dateien sollte man mit der ``with``-Anweisung öffnen, dann ist das korrekte Schliessen sichergestellt.
Funktionen oder Methoden sollten das Programm nicht abbrechen. `sys.exit()` gehört nicht in Programmlogik, die nur Daten verarbeitet, sondern höchstens in Programmteile, welche die Benutzerinteraktion abwickeln.
Die Aktion `data` erst mit Komma zusammenzuführen um gleich in der nächsten Zeile das ganze an dem gerade dazwischen gefügten Komma wieder aufzuteilen ist ziemlich sinnfrei.
Beim Namen `name` würde kaum jemand vermuten das sich da eine Liste mit *Zahlen* hinter verbirgt. Beim Erstellen der Liste teilst Du am Komma -- in der Beschreibung der Eingabedaten sind die Zahlen aber durch Leerzeichen getrennt!?
`report` ist auch nicht an etwas gebunden was ein Report wäre, sondern ja wohl an einen Namen. Was die Bindung von `name` an eine Liste mit Zahlen noch verwirrender macht.
Aus den letzten beiden Punkten ergibt sich, dass der Name `report2name` ebenfalls verwirrend und falsch ist.
Der Namenszusatz `Obj` ist übrigens in der Regel ziemlich überflüssig -- *alles* was man in Python an einen Namen binden kann ist ein Objekt. Der Zusatz `Obj` enthält also hier absolut keine zusätzliche Information.
Ich würde erst einmal bei Funktionen bleiben solange es keinen Grund für eine Klasse gibt.
Dann solltest Du das Problem in einzelne Schritte unterteilen bis die so klein sind, dass sie mehr oder weniger trivial implementiert werden können. Das machst Du dann und setzt die Teillösungen zu einer Gesamtlösung zusammen.
Das könnte zum Beispiel mit einer Funktion beginnen, die eine CSV-Datei einliesst und als Ergebnis ein Wörterbuch, das Namen auf Mittelwerte abbildet zurück gibt.
Die kann man dann auf mehrere Report-Dateien anwenden und die Ergebnisse in einer Liste sammeln, die Tupel aus Reportnamen und den Ergebnissen von der Einlesefunktion enthält.
Dann brauchst Du nur noch eine Funktion die das ganze entsprechend für die Ausgabe aufbereitet. Das liesse sich unterteilen in Kopfzeile erstellen und dann eine Zeile für jeden Report erstellen.
Und wichtig beim Entwickeln: Jeden Schritt testen und erst mit der nächsten Funktion weitermachen, wenn das Teilergebnis bis dahin funktioniert.
Der Quelltext ist zu kompliziert. Insbesondere ist die Klasse unsinnig. Das erkennt man vielleicht auch schon am Namen, der bei Klassen übrigens mit einem Grossbuchstaben beginnen sollte. Klassen beschreiben "Dinge" während Funktionen und Methoden "Tätigkeiten" beschreiben. `readInCSV` ist keine Beschreibung für ein "Ding".
Attribute sollte man auch alle in der `__init__` definieren. Wenn bei Methodenaufrufen welche hinzukommen wird es schnell unübersichtlich und fehleranfällig. Zumal in `average()` auch Werte an das `readInCSV`-Exemplar gebunden werden, die eindeutig nur innerhalb der Methode von Interesse sind. Andererseits sehe ich keinen Sinn darin auf `self.report` und `self.name` zuzugreifen und damit wäre das einfach nur eine Funktion und keine Methode.
Dateien sollte man mit der ``with``-Anweisung öffnen, dann ist das korrekte Schliessen sichergestellt.
Funktionen oder Methoden sollten das Programm nicht abbrechen. `sys.exit()` gehört nicht in Programmlogik, die nur Daten verarbeitet, sondern höchstens in Programmteile, welche die Benutzerinteraktion abwickeln.
Die Aktion `data` erst mit Komma zusammenzuführen um gleich in der nächsten Zeile das ganze an dem gerade dazwischen gefügten Komma wieder aufzuteilen ist ziemlich sinnfrei.
Beim Namen `name` würde kaum jemand vermuten das sich da eine Liste mit *Zahlen* hinter verbirgt. Beim Erstellen der Liste teilst Du am Komma -- in der Beschreibung der Eingabedaten sind die Zahlen aber durch Leerzeichen getrennt!?
`report` ist auch nicht an etwas gebunden was ein Report wäre, sondern ja wohl an einen Namen. Was die Bindung von `name` an eine Liste mit Zahlen noch verwirrender macht.
Aus den letzten beiden Punkten ergibt sich, dass der Name `report2name` ebenfalls verwirrend und falsch ist.
Der Namenszusatz `Obj` ist übrigens in der Regel ziemlich überflüssig -- *alles* was man in Python an einen Namen binden kann ist ein Objekt. Der Zusatz `Obj` enthält also hier absolut keine zusätzliche Information.
Ich würde erst einmal bei Funktionen bleiben solange es keinen Grund für eine Klasse gibt.
Dann solltest Du das Problem in einzelne Schritte unterteilen bis die so klein sind, dass sie mehr oder weniger trivial implementiert werden können. Das machst Du dann und setzt die Teillösungen zu einer Gesamtlösung zusammen.
Das könnte zum Beispiel mit einer Funktion beginnen, die eine CSV-Datei einliesst und als Ergebnis ein Wörterbuch, das Namen auf Mittelwerte abbildet zurück gibt.
Die kann man dann auf mehrere Report-Dateien anwenden und die Ergebnisse in einer Liste sammeln, die Tupel aus Reportnamen und den Ergebnissen von der Einlesefunktion enthält.
Dann brauchst Du nur noch eine Funktion die das ganze entsprechend für die Ausgabe aufbereitet. Das liesse sich unterteilen in Kopfzeile erstellen und dann eine Zeile für jeden Report erstellen.
Und wichtig beim Entwickeln: Jeden Schritt testen und erst mit der nächsten Funktion weitermachen, wenn das Teilergebnis bis dahin funktioniert.