Auswerten einer txt-Datei

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
cube.

Hallo zusammen,

Ich bin absoluter Anfänger in Sachen Programmieren und wurde im Rahmen eines Praktikums (Studium) damit beauftragt, ein "einfaches" Skript zur Auswertung von Txt-Dateien zu schreiben.
"Einfach" bedeutet natürlich, dass es für mich trotzdem eine Herausforderung ist. ,-)
Bisher habe ich hauptsächlich das OpenBook von Galileo zum Thema Python gelesen, daher stammen also meine Kenntnisse.
Aber nun zur Aufgabe selbst.

Meine Ausgangsdaten sehen wie folgt aus:

Code: Alles auswählen

0,2000-01-01T00:00:00Z
0,2000-01-01T01:00:00Z
0,2000-01-01T02:00:00Z
0,2000-01-01T03:00:00Z
Ziel ist, für alle Tage einen durchschnittlichen Wert (Zahl vor dem Komma) zu errechnen.
Dazu müssten in meinen Augen folgende Schritte unternommen werden (bitte berichtigt mich!):
1. "T" und "Z" eliminieren bzw. ggf. durch Kommata und Leerzeichen ersetzen (s.u.)
2. immer jeweils 24 Werte aufgrund des Datums addieren
3. Ergebnis durch 24 teilen

Bisher bin ich leider erst so weit:

Code: Alles auswählen

import os
os.chdir ('C:\x')

with open('Test.txt') as a_file:
    for a_line in a_file:
        print (a_line.rstrip())

string = a_line

for a_line in string:
    string = string.replace("T" , ",")
    string = string.replace("Z" , "")

print (string)
Im Ergebnis bekomme ich im Moment alle Zeilen ausgegeben, leider werden aber nur in der letzten Zeile "T" durch ein Komma und "Z" durch Nichts ersetzt - wo liegt der Fehler in der Schleife?
Ferner bin ich natürlich auch für alle Hinweise bezüglich des Rests dankbar...

Gruß
cube.
Benutzeravatar
/me
User
Beiträge: 3556
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

cube. hat geschrieben:

Code: Alles auswählen

[...]
string = a_line

for a_line in string:
    string = string.replace("T" , ",")
    string = string.replace("Z" , "")
Dieses Codefragment ist mit "Humbug" noch sehr wohlwollend umschrieben. :wink:

a_line enthält zu Beginn die letzte Zeile die du eingelesen hast. Diese schiebst du nach string. string ist übrigens nicht nur ein nichtssagender, sondern auch ein schlecht gewählter Name, da string schon in der Standardbibliothek verwendet wird.

Jetzt iterierst du über den String. In der Schleife nimmt a_line der Reihe nach den Wert jedes einzelnen Zeichens in dem String an. Genau so oft ersetzt du in der Schleife jetzt in diesem einen String, also deiner letzten gelesenen Zeile, ein "T" durch ein Komma und ein "Z" durch nichts. Das einmal zu machen würde ja völlig ausreichen.

Zum Einlesen selber würde ich das csv-Modul vorschlagen.

Ich erkläre gerne weiter, aber erst solltest du wirklich verstanden haben was da passiert. Streu doch mal an den passenden Stellen noch einige print-Aufrufe ein und lass dir ausgeben was die Variablen tatsächlich enthalten und was somit eigentlich vorgeht.
BlackJack

@cube.: Bei den Punken 2. und 3. ist die 24 wahrscheinlich nur ein Beispiel, denn was Du eigentlich machen musst ist alle Messwerte an einem Tag zusammen addieren und dann durch die Anzahl der Werte an einem Tag teilen. Wenn das grundsätzlich immer 24 wären, bräuchte man die Spalte mit den Zeitstempeln nicht wirklich.

Du musst das Problem in kleinere Teilprobleme aufteilen, bis die so einfach werden, dass man sie mit einer Funktion in ein paar Zeilen Code lösen kann. Und aus den ganzen Teillösungen kann man dann grössere Teillösungen und am Ende eine Gesamtlösung zusammensetzen.

Mal Vorschläge für Schritte mit Beispielen für diese Daten:

Code: Alles auswählen

1,2000-01-01T00:00:00Z
2,2000-01-01T01:00:00Z
3,2000-01-01T02:00:00Z
4,2000-01-01T03:00:00Z
5,2000-02-01T00:00:00Z
6,2000-02-01T01:00:00Z
7,2000-02-01T02:00:00Z
8,2000-02-01T03:00:00Z
1. Einlesen der Datei in eine verschachtelte Liste also eine Liste welche eine Liste pro Dateizeile mit den Spaltenwerten als Zeichenketten enthält. Das `csv`-Modul wurde ja schon erwähnt.

Code: Alles auswählen

[['1', '2000-01-01T00:00:00Z'],
 ['2', '2000-01-01T01:00:00Z'],
 ['3', '2000-01-01T02:00:00Z'],
 ['4', '2000-01-01T03:00:00Z'],
 ['5', '2000-02-01T00:00:00Z'],
 ['6', '2000-02-01T01:00:00Z'],
 ['7', '2000-02-01T02:00:00Z'],
 ['8', '2000-02-01T03:00:00Z']]
2. Umwandeln der Liste in eine die nicht mehr Zeichenketten als innerste Werte enthält, sondern Zahlen als erste Zeilenelemente und Datumsangaben als zweite Zeilenelemente. Für Datumsangaben gibt es das `datetime`-Modul mit einem `datetime`-Typ der sich hier geradezu anbietet.

Auch hier kann man das Problem nochmal ganz einfach zerlegen, denn um alle Elemente in einer Liste umzuwandeln, kann man eine Funktion schreiben die *ein* Element umwandelt, und dann diese Funktion auf alle Elemente anwenden. Die `map()`-Funktion kann dabei hilfreich sein.

Code: Alles auswählen

[[1.0, datetime.datetime(2000, 1, 1, 0, 0)],
 [2.0, datetime.datetime(2000, 1, 1, 1, 0)],
 [3.0, datetime.datetime(2000, 1, 1, 2, 0)],
 [4.0, datetime.datetime(2000, 1, 1, 3, 0)],
 [5.0, datetime.datetime(2000, 2, 1, 0, 0)],
 [6.0, datetime.datetime(2000, 2, 1, 1, 0)],
 [7.0, datetime.datetime(2000, 2, 1, 2, 0)],
 [8.0, datetime.datetime(2000, 2, 1, 3, 0)]]
Da man die Zeit nicht benötigt, kann man sie eigentlich auch in diesem Schritt auch verwerfen und nur `datetime.date`-Objekte verwenden.

Code: Alles auswählen

[[1.0, datetime.date(2000, 1, 1)],
 [2.0, datetime.date(2000, 1, 1)],
 [3.0, datetime.date(2000, 1, 1)],
 [4.0, datetime.date(2000, 1, 1)],
 [5.0, datetime.date(2000, 2, 1)],
 [6.0, datetime.date(2000, 2, 1)],
 [7.0, datetime.date(2000, 2, 1)],
 [8.0, datetime.date(2000, 2, 1)]]
3. Gruppieren der Werte nach Datum. Für jeweils ein Datum alle Werte in einer Liste sammeln. Dabei kann `itertools.groupby()` nützlich sein, wenn man das nicht selber nachprogrammieren will.

Code: Alles auswählen

[[datetime.date(2000, 1, 1), [1.0, 2.0, 3.0, 4.0]],
 [datetime.date(2000, 2, 1), [5.0, 6.0, 7.0, 8.0]]]
4. Eine Funktion die den Durchschnitt von einer Liste mit Werten berechnet. Und die dann verwenden um, naja eben den Durchschnitt auszurechnen.

Code: Alles auswählen

[[datetime.date(2000, 1, 1), 2.5], [datetime.date(2000, 2, 1), 6.5]]
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

@BlackJack: Sehr schöne Darstellung! :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
cube.

@ /me, BlackJack: Danke für die Hinweise. Ich merke doch sehr, dass ich nur anhand eines gelesenen Lehrbuchs am praktischen Beispiel nicht so weit komme. Aus dem Grund bin ich auch lediglich mit dem ersten Schritt fertig:

Code: Alles auswählen

import csv
with open('Test.csv') as f:
    reader = csv.reader(f)
    for row in reader:
        print (row)
Bereits bei der Beschreibung des datetime-Befehls habe ich es nicht geschafft, daraus den richtigen Befehl in mein Skript zu integrieren.
Es mutet zwar nach Hausaufgabenhilfe an, aber würdest Du, BlackJack, mir noch ein paar Hinweise geben können, wie der Code in etwas aussehen müsste?
Das würde mir sehr weiterhelfen, weil ich das komplette Openbook wohl nicht mehr in den verbleibenden 2 1/2 Wochen Praktikum durchackern kann...

Gruß
cube.

PS: Eine Sache habe ich wohl durcheinander gebracht - die Werte sollen nicht durch die Anzahl der Tageswerte dividiert, sondern lediglich aufsummiert werden.
BlackJack

@cube.: Du suchst die `strptime()`-Methode vom `datetime`-Datentyp, damit kann man Zeichenketten mittels einer Formatzeichenkette in `datetime`-Objekte umwandeln. Zumindest zusätzlich zum OpenBook könntest Du auch in die Python-Dokumentation schauen.

Das was Du bis jetzt hast ist weder in einer Funktion, noch werden dort die Daten in eine Datenstruktur eingelesen. Du solltest wirklich Schritt für Schritt vorgehen und Funktionen schreiben die nacheinander angewendet die Eingabedaten in die Ausgabedaten umwandeln. Kleinere Teilprobleme lassen sich einfacher lösen und auch testen ob man soweit alles richtig gemacht hat, als eine grosse Lösung.

Edit: Das letzte Ergenis sähe dann so aus, und eine Funktion zum aufsummieren muss man nicht selber schreiben, die gibt es schon in den eingebauten Funktionen von Python :-)

Code: Alles auswählen

[[datetime.date(2000, 1, 1), 10.0], [datetime.date(2000, 2, 1), 26.0]]
Antworten