Zeilen verwerfen

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
alex1990ge
User
Beiträge: 22
Registriert: Freitag 26. Juli 2013, 10:04

Hallo,

ich bin absoluter programmier und Python Neuling.
Ich muss nun für meine Bachelorarbeit einige tausend Textdateien mit Messdaten in die von mir gewünschte Form bringen.
Das klappt auch soweit gut, allerdings habe ich noch ein Problem:

Wie kann ich einzelne Zeilen auslesen und diese in einer zweiten Datei wieder abspeichern.

mit den Zeilen habe ich es bisher so gelößt:

Code: Alles auswählen

obj_in = open("1Star_000560_083.606250_-06.896405_04900_00448_000_002546_001.45_99.36_99_lc.dat")
obj_out = open("2-Star_000560_083.606250_-06.896405_04900_00448_000_002546_001.45_99.36_99_lc.txt","w")
for line in obj_in:
    row = line.split()
    t = float(row[0])
    x = float(row[1])
    obj_out.write("%g\t%g\n" % (t, x))
obj_in.close()
obj_out.close()
Danke für eue Hilfe!
BlackJack

@alex1990ge: Nach welchen Kriterien sollen denn Zeilen verworfen werden? Kann man das pro Zeile anhand von Werten in der jeweiligen Zeile entscheiden? Oder geht es um bestimmte Zeilenbereiche? Wie werden die identifiziert?
alex1990ge
User
Beiträge: 22
Registriert: Freitag 26. Juli 2013, 10:04

Hallo BlackJack!

Ich möchte aus jeder Datei die ersten drei Zeilen verwerfen, da diese Überschriften sind, die mein Analyseprogramm nicht einlesen kann.
BlackJack

@alex1990ge:

Code: Alles auswählen

for line in islice(obj_in, 3, None):
`islice()` ist aus dem `itertools`-Modul.
alex1990ge
User
Beiträge: 22
Registriert: Freitag 26. Juli 2013, 10:04

Ich habe das jetzt wie folgt eingebaut:

Code: Alles auswählen

import itertools

obj_in = open("Star_000560_083.606250_-06.896405_04900_00448_000_002546_001.45_99.36_99_lc.dat")
obj_out = open("2-Star_000560_083.606250_-06.896405_04900_00448_000_002546_001.45_99.36_99_lc.txt","w")

for line in islice(obj_in, 3, None):
    row = line.split()
    t = float(row[0])
    x = float(row[1])

    obj_out.write("%g\t%g\n" % (t, x))

obj_in.close()
obj_out.close()
Allerdings kommt dann die Fehlermeldung: 'islice' is not defined

Woran kann das liegen? Richtig importiert sollte itertools doch sein, da ansonsten ja schon vorher ein Fehler auftauchen würde, oder?
BlackJack

@alex1990ge: Du hast das Modul importiert, damit sind nicht automatisch alle Namen aus dem Modul auch im importierenden Modul. Du musst also entweder `islice()` über das Modul ansprechen ``itertools.islice(obj_in, 3, None)`` oder aber die Funktion importieren: ``from itertools import islice``.
alex1990ge
User
Beiträge: 22
Registriert: Freitag 26. Juli 2013, 10:04

Das funktioniert super, danke!

Eine weitere Frage habe ich noch:
die erste eingelesene Spalte wird nur mit einer Nachkommastelle ausgegeben, obwohl sie 4 hat.
Wodran liegt das, und wie kann ich das ändern?

Als kleines Beispiel:
input File
56322.0972

output file
56322.1
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Schau dir mal das Kapitle zu String Formatting in der Dokumentation an, da kannst du die Details der Ausgabe festlegen. Am einfachsten ist es aber wohl, wenn du die Werte gar nicht erst in floats umwandelst, sondern die Strings wieder blind wegschreibst:

Code: Alles auswählen

obj_out.write("%s\t%s\n" % (row[0], row[1]))
Das Leben ist wie ein Tennisball.
BlackJack

@alex1990ge: Das liegt am Formatcode '%g' ohne weitere Angaben zur Länge:

Code: Alles auswählen

In [20]: '%g' % 56322.0972
Out[20]: '56322.1'

In [21]: '%f' % 56322.0972
Out[21]: '56322.097200'

In [22]: '%s' % 56322.0972
Out[22]: '56322.0972'
alex1990ge
User
Beiträge: 22
Registriert: Freitag 26. Juli 2013, 10:04

Danke!
Das Kapitel werde ich mir gleich mal durchlesen... ich habe noch viel zu lernen ;)
alex1990ge
User
Beiträge: 22
Registriert: Freitag 26. Juli 2013, 10:04

Mit einem File klappt das nun alles wunderbar.

Der nächste Schritt wäre das automatisiert mit allen files in einem Ordner durchzuführen.
Habt ihr noch einen Tipp für mich, oder etwas wo sowas erklärt wird?
BlackJack

@alex1990ge: Du suchst wahrscheinlich das `os`-Modul mit `os.listdir()` und den Funktionen in `os.path` oder das `glob`-Modul (und die Funktionen in `os.path`).
alex1990ge
User
Beiträge: 22
Registriert: Freitag 26. Juli 2013, 10:04

@BlackJack:

ja genau sowas habe ich gesucht.
habe das wie folgt eingebaut, aber es funktioniert nicht:

Code: Alles auswählen

import glob
import itertools
from itertools import islice

input = glob.glob("LC/*.dat")
output = glob.glob("LC/newLCs/LP-*.txt")

for f in input: 
   obj_in = open("f")

for f in output:
   obj_out = open("f","w")

for line in islice(obj_in, 3, None):
    column = line.split()
    t = str(column[0])
    x = str(column[1])

    obj_out.write("%s\t%s\n" % (t, x))

obj_in.close()
obj_out.close()
Woran liegts?
BlackJack

@alex1990ge: Das sieht nach einfach wild geraten ein komplettes Programm hingetippt, in der Hoffnung, dass das irgendwie das tut was man möchte. So funktioniert Programmieren nicht. Man *entwickelt* Programme. Und zwar Stück für Stück, inklusive Testen ob das was man bisher hat, soweit funktioniert wie man sich das vorgestellt hat.

Bei Deinem Programm fängt es wahrscheinlich damit an, dass `output` nicht unbedingt das enthalten muss, wass Du vielleicht erwartest. Es sei denn es gibt dort die Ausgabedateinamen schon alle. Wobei dann immer noch das Problem bestünde, dass `glob()` keine Garantien über die Reihenfolge macht. Also selbst wenn dort zu jeder Eingabedatei schon eine Ausgabedatei existiert, die überschrieben werden soll, müsste man die immer noch irgendwie richtig zuordnen.

Dann hast Du zwei Schleifen in denen immer wieder eine Datei mit dem Namen 'f' geöffnet wird und an den Namen `obj_in` beziehungsweise `obj_out` gebunden wird. Wobei man einen Namen natürlich immer nur an einen Wert zu einer gegebenen Zeit binden kann. Das heisst nach jedem Schleifendurchlauf kann man auf den vorherigen Wert von `obj_in` beziehungsweise `obj_out` nicht mehr zugreifen. Wenn man Glück hat sind es wenige Dateien oder die Speicherbereinigung räumt die zeitnah ab — oder man bekommt vom Betriebsystem eins auf die Finger weil man zu viele Dateien geöffnet und nicht wieder geschlossen hat.

In der ersten Schleife wird das Programm wahrscheinlich dann auch mit einer Fehlermeldung aussteigen, es sei denn Du hast zufällig eine Datei mit dem Namen 'f' die man öffnen könnte.

Also Vorgehensweise: Eingabedateipfade ermitteln. Testen! Also eine Schleife schreiben, die einfach erst einmal nur die Pfade ausgibt. Dann den Ausgabepfad mit `os.path`-Funktionen aus dem Eingabepfad erstellen (das ist das was Du wohl *eigentlich* machen möchtest). Testen! Dann den Code zum Umwandeln in eine Funktion stecken und die von dem bis dahin entwickelten Code aufrufen lassen. Testen! Fertig.

Die 'Testen!' im letzten Absatz sind harte Grenzen. Solange es bis dahin nicht funktioniert, nichts neues anfangen sondern erst einmal bis zu dem Punkt zum Laufen bringen.
alex1990ge
User
Beiträge: 22
Registriert: Freitag 26. Juli 2013, 10:04

stimmt, ist auch alles einfach zusammengewürfelt :D

habe jetzt noch eine Lösung gefunden, die genau das tut was ich will:

Code: Alles auswählen

import glob
import itertools
from itertools import islice

input = glob.glob("LC/*.dat")

#dateiliste = glob.glob("LC/)

for f in input: 
   obj_in = open(f)
   obj_out = open(f+'.txt',"w")
   for line in islice(obj_in, 3, None):
      column = line.split()
      t = str(column[0])
      x = str(column[1])

      obj_out.write("%s\t%s\n" % (t, x))

   obj_in.close()
   obj_out.close()
nezzcarth
User
Beiträge: 1635
Registriert: Samstag 16. April 2011, 12:47

Bist du denn eigentlich darauf festgelegt, das mit Python zu machen? Weil je nachdem gäb' es da durchaus leichtere Wege (z.B. mit R oder awk) solche einfachen Transformationen durchzuführen, die du dir vielleicht mal anschauen kannst, wenn solche Aufgaben öfter anstehen sollten...
Zuletzt geändert von nezzcarth am Freitag 26. Juli 2013, 16:52, insgesamt 1-mal geändert.
BlackJack

@nezzcarth: Ob das mit R oder awk leichter ist kommt vielleicht auch darauf an ob und wie gut man sich mit denen auskennt. Ich denke wenn man in allen von Null anfängt, dann nehmen die sich nicht viel.
alex1990ge
User
Beiträge: 22
Registriert: Freitag 26. Juli 2013, 10:04

Nein, da gab es keine genaue Festlegung.
Aber da ich wusste, dass man mit Python sowas machen kann bin ich drauf gekommen.
Antworten