string und array in ascii datei speichern

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
pynew
User
Beiträge: 4
Registriert: Freitag 10. Mai 2013, 09:40

Hey Leute, ich habe nun angefangen in Python zu programmieren. Dies ist meine erste Programmiersprache die ich lerne und nun bin ich auf ein Problem gestoßen, das mir ehrlich gesagt kopf zerbrechen bereitet :)
ich habe schon gesucht, aber nichts dazu gefunden, hoffe ihr könnt mir helfen :wink:

im prinzip möchte ich in die erste Zeile einer .asc Datei die Variablen "t", "x" und "y" schreiben.
und darunten in Spalten die Matrix. Man kann sich dies also als Messung vorstellen, die Zeitwerte t und in meinem Beispiel stellt sin(t) x dar und cos(t) ist y. Die matrix mit den Werten ist ein array und die erste Zeile mit den Variablen ist ein String, oder kann man das anders implementieren?

aber hier jetzt mal mein code:

Code: Alles auswählen

import numpy as np

t=np.arange(0.0,10.0,0.5)     
x=np.sin(t)
y=np.cos(t)


M=np.column_stack((t.T,x.T,y.T))    # M ist Matrix, in der als Spalten die Werte t,x,y stehen
print M

g="{0:5}{1:11}{1:6}{2:12}{2:7}{3:13}"
c=(g.format(" ","t"," ","x"," ","y"))
h="\n"\

f=open("save.asc","w")
f.write(c)
f.write(h)

np.savetxt("save.asc",M,fmt="%15.6e")
f.close()

b=np.genfromtxt("save.asc")
print b
und das Ergebnis was herauskommt ist:

Code: Alles auswählen

     t          t                        x            000000e-01    4.794255e-01    8.775826e-01
   1.000000e+00    8.414710e-01    5.403023e-01
   1.500000e+00    9.974950e-01    7.073720e-02
   2.000000e+00    9.092974e-01   -4.161468e-01
   2.500000e+00    5.984721e-01   -8.011436e-01
   3.000000e+00    1.411200e-01   -9.899925e-01
   3.500000e+00   -3.507832e-01   -9.364567e-01
   4.000000e+00   -7.568025e-01   -6.536436e-01
   4.500000e+00   -9.775301e-01   -2.107958e-01
   5.000000e+00   -9.589243e-01    2.836622e-01
   5.500000e+00   -7.055403e-01    7.086698e-01
   6.000000e+00   -2.794155e-01    9.601703e-01
   6.500000e+00    2.151200e-01    9.765876e-01
   7.000000e+00    6.569866e-01    7.539023e-01
   7.500000e+00    9.380000e-01    3.466353e-01
   8.000000e+00    9.893582e-01   -1.455000e-01
   8.500000e+00    7.984871e-01   -6.020119e-01
   9.000000e+00    4.121185e-01   -9.111303e-01
   9.500000e+00   -7.515112e-02   -9.971722e-01
also es sollte nicht t,t,x in der ersten Zeile stehen, sondern t,x,y
die werte in der ersten Zeile am schluss gehören dort auch nicht hin.

Hoffe mir kann jemand helfen, hab schon ewig rumprobiert, aber bin auf nichts vernünftiges gekommen :K
Ah und falls das im falschen Unterforum stehen sollte, bitte verschiebt es, ich wusste nicht wo genau hin damit :wink:
Zuletzt geändert von Anonymous am Freitag 10. Mai 2013, 09:59, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

Hallo pynew,

schau Dir in der Dokumentation nochmal an was »str.format« macht. Vor allem, wie man in angibt, welches der Argumente benutzt werden soll.
Zum zweiten Problem: Du schreibst zweimal in die gleiche Datei "save.asc" mit verschiedenen Filehandles gleichzeitig. Was in welcher Reihenfolge dann in der Datei steht ist damit undefiniert. Zum Glück kann »np.savetxt« auch in Filehandles schreiben, dann tritt das Problem nicht auf.
BlackJack

@pynew: Das da 't' zweimal geschrieben wird, liegt daran, dass *Du* sagst, das es zweimal geschrieben werden soll. Vielleicht solltest Du das `format()` nicht so unnötig kompliziert machen, dann blickt man da einfacher durch welcher Wert, wie und wohin formatiert wird. Man muss da auch nicht jedes Zwischenergebnis an einen eigenen Namen binden und auch das Zeilenendezeichen kann man direkt in die Formatvorlage schreiben, statt es separat zu schreiben.

Das Schreiben in die Datei kann so grundsätzlich nicht funktionieren, weil die Datei zweimal zum Schreiben geöffnet wird. Einmal explizit mit `open()` und dann noch mal innerhalb von `np.savetxt()`. Welcher Teil von diesen beiden Schreiboperationen dann wo in der Datei landet, beziehungsweise ob überhaupt, ist mehr oder weniger Zufall, beziehungsweise hängt von Faktoren wie Puffergrössen des Betriebssystems ab, die nicht unter der Kontrolle des Programmierers sind. Du darfst da keinen Dateinamen übergeben, sondern musst das selbe Dateiobjekt übergeben in dass Du auch schon die Kopfzeile geschrieben hast.

Zum Öffnen von Dateien sollte man die ``with``-Anweisung verwenden, damit die Datei auch unter allen Umständen wieder geschlossen wird.
Benutzeravatar
/me
User
Beiträge: 3561
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

pynew hat geschrieben:

Code: Alles auswählen

g="{0:5}{1:11}{1:6}{2:12}{2:7}{3:13}"
c=(g.format(" ","t"," ","x"," ","y"))
Zu Beginn möchte ich dir den Hinweis geben dir mal PEP-8, den Style Guide für Python anzusehen.

So sieht es besser aus.

Code: Alles auswählen

header_template = "{0:5}{1:11}{1:6}{2:12}{2:7}{3:13}"
header = header_template.format(" ","t"," ","x"," ","y")
Oder direkt so.

Code: Alles auswählen

header = "{0:5}{1:11}{1:6}{2:12}{2:7}{3:13}".format(" ","t"," ","x"," ","y")
Jetzt hast du ein Problem mit der Ausgabe der ersten Zeile. Es erscheinen nicht die Werte die du erwartest. Andererseits macht Python hier alles richtig. Der erste zu ersetzende Ausdruck im Format-String ist {0:5}. Du bekommst dort den ersten Parameter (Index 0) auf 5 Zeichen aufgefüllt. Danach kommt dann {1:11} und danach wird es dann merkwürdig. Mit {1:6} greifst du wieder auf den gleichen Parameterwert zu. Anscheinend hast du das Hochzählen vergessen.

Den Zeilenumbruch könntest du übrigens direkt in den Formatstring hineinnehmen.

Code: Alles auswählen

header = '{0:5}{1:11}{2:6}{3:12}{4:7}{5:13}\n'.format(' ', 't', ' ', 'x', ' ', 'y')
Mir ist allerdings noch nicht klar, warum du hier überhaupt einen Formatstring verwendest oder nicht zumindest die Leerzeichen aus der Parameterliste in den String verlagerst.
pynew
User
Beiträge: 4
Registriert: Freitag 10. Mai 2013, 09:40

klasse, danke euch erstmal für die schnellen Antworten.

neuer code:

Code: Alles auswählen

import numpy as np


t=np.arange(0.0,10.0,0.5)
x=np.sin(t)
y=np.cos(t)



M=np.column_stack((t.T,x.T,y.T))
print M

#g="{0:12}{1:12}{2:12}"
#c=(g.format("t","x","y\n"))
header = '{0:5}{1:11}{2:6}{3:12}{4:7}{5:13}\n'.format(' ', 't', ' ', 'x', ' ', 'y')

with open("save.asc","w") as f:
    f.write(header)
    np.savetxt("save.asc",M,fmt="%15.6e")
    f.close()

#b=np.loadtxt("save.asc")
b=np.genfromtxt("save.asc")
print b

und was rauskommt:

Code: Alles auswählen

     t                x                  y            
0000e-01    4.794255e-01    8.775826e-01
   1.000000e+00    8.414710e-01    5.403023e-01
   1.500000e+00    9.974950e-01    7.073720e-02
   2.000000e+00    9.092974e-01   -4.161468e-01
   2.500000e+00    5.984721e-01   -8.011436e-01
   3.000000e+00    1.411200e-01   -9.899925e-01
   3.500000e+00   -3.507832e-01   -9.364567e-01
   4.000000e+00   -7.568025e-01   -6.536436e-01
   4.500000e+00   -9.775301e-01   -2.107958e-01
   5.000000e+00   -9.589243e-01    2.836622e-01
   5.500000e+00   -7.055403e-01    7.086698e-01
   6.000000e+00   -2.794155e-01    9.601703e-01
   6.500000e+00    2.151200e-01    9.765876e-01
   7.000000e+00    6.569866e-01    7.539023e-01
   7.500000e+00    9.380000e-01    3.466353e-01
   8.000000e+00    9.893582e-01   -1.455000e-01
   8.500000e+00    7.984871e-01   -6.020119e-01
   9.000000e+00    4.121185e-01   -9.111303e-01
   9.500000e+00   -7.515112e-02   -9.971722e-01
also mit der ersten Zeile passt das jetzt so.
Weshalb ich das mit Format machen?

Anfangs habe ich das so probiert:

Code: Alles auswählen

s="          t                    x                      y\n"

aber das hat mich nicht weitergebracht, deshalb habe ich mir gedacht, es könnte ja mit .format funktionieren und hab das dann probiert
oder gäbe es einen einfacheren Weg?

Genau das ist mein Problem im Moment, ich möchte in die gleiche Datei, zuerst die Kopfzeile und dann die Werte einlesen, so dass sie "geordnet" in richtiger Reihenfolge herauskommen. Wie kann ich das am besten angehen?

und @sirius3 , sorry, aber was heißt "Filehandles" ? :roll: wie gesagt, bin voller Anfänger :wink:
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

@pynew: den Zeilenumbruch würde ich noch in den Formattext und nicht in die Argumente nehmen.
Mit Filehandle meine ich eigentlich ein Fileobjekt, bei Dir »f«. Wenn Du nun noch in »savetxt« statt des ersten Arguments "save.asc" »f« schreibst, müsste alles so sein, wie Du erwartest.
pynew
User
Beiträge: 4
Registriert: Freitag 10. Mai 2013, 09:40

danke dir sirius!

Code: Alles auswählen

import numpy as np


t=np.arange(0.0,10.0,0.5)
x=np.sin(t)
y=np.cos(t)



M=np.column_stack((t.T,x.T,y.T))
print M


header = '{0:9}{1:11}{2:6}{3:10}{4:5}{5:13}'.format(' ', 't', ' ', 'x', ' ', 'y\n')

with open("save.asc","w") as f:
    f.write(header)
    np.savetxt(f,M,fmt="%15.4e")
    f.close()

b=np.genfromtxt("save.asc")
print b
aber letztes Problem, die erste Zeile der Matrix ist verschoben, wodurch wird das verursacht?

Code: Alles auswählen

         t                x              y
                0.0000e+00      0.0000e+00      1.0000e+00
     5.0000e-01      4.7943e-01      8.7758e-01
     1.0000e+00      8.4147e-01      5.4030e-01
     1.5000e+00      9.9749e-01      7.0737e-02
     2.0000e+00      9.0930e-01     -4.1615e-01
     2.5000e+00      5.9847e-01     -8.0114e-01
     3.0000e+00      1.4112e-01     -9.8999e-01
     3.5000e+00     -3.5078e-01     -9.3646e-01
     4.0000e+00     -7.5680e-01     -6.5364e-01
     4.5000e+00     -9.7753e-01     -2.1080e-01
     5.0000e+00     -9.5892e-01      2.8366e-01
     5.5000e+00     -7.0554e-01      7.0867e-01
     6.0000e+00     -2.7942e-01      9.6017e-01
     6.5000e+00      2.1512e-01      9.7659e-01
     7.0000e+00      6.5699e-01      7.5390e-01
     7.5000e+00      9.3800e-01      3.4664e-01
     8.0000e+00      9.8936e-01     -1.4550e-01
     8.5000e+00      7.9849e-01     -6.0201e-01
     9.0000e+00      4.1212e-01     -9.1113e-01
     9.5000e+00     -7.5151e-02     -9.9717e-01
und allgemeine Fragen noch:
- wenn ich ein array wie hier in eine Datei schreiben möchte, nutze ich den Befehl np.savetxt oder gibts dazu alternativen?

- und wenn ich die datei lesen will, muss ich np.genfromtxt nutzen, weil ein array drin ist, und ein "normaler" "read"-Befehl, dieses array nicht lesen kann oder? gibts dazu alternativen? np.loadtxt kann ja nur dateien laden, in denen keine Strings stehen, oder hab ich das falsch verstanden?
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

pynew hat geschrieben:

Code: Alles auswählen

header = '{0:9}{1:11}{2:6}{3:10}{4:5}{5:13}'.format(' ', 't', ' ', 'x', ' ', 'y\n')
aber letztes Problem, die erste Zeile der Matrix ist verschoben, wodurch wird das verursacht?
Das liegt daran, dass es den String 'y\n' rechts auffüllt, und da entsteht dann eben das hier:

Code: Alles auswählen

>>> '{:13}'.format('y\n')
'y\n           '
>>> 
Außerdem benutzt man with gerade deshalb, weil man da die Datei nicht explizit schließen muss. Die Zeile f.close() ist falsch.
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

@pynew: schau Dir nochmal genau an, wie Dein »header« aussieht ;-) und beachte meine erste Anmerkung.
Es gibt viele Möglichkeiten aus Textdateien Arrays zu lesen, aber kaum einfachere. Aber was stört Dich an »genfromtext« genau jetzt?
BlackJack

@pynew: Die verschobene zweite Zeile liegt daran, dass Du das Zeilenende-Zeichen an der falschen Stelle eingefügt hast. Das ist doch gar nicht Teil der letzten Spaltenüberschrift, sondern sollte ans *Ende* der Zeile. Also in die Formatvorlage für die Zeile.

`numpy.savetext()` bietet sich hier an, weil es das halt schon gibt und das anscheinend die Daten in einem Format schreibt, welches Du haben möchtest.

Zum Lesen kann man auch `numpy.loadtext()` nehmen. Denn die Daten enthalten ja nur Zahlen. Die Kopfzeile müsstest Du bei beiden Funktionen mit dem entsprechenden Argument (`skip_header`) ignorieren.
pynew
User
Beiträge: 4
Registriert: Freitag 10. Mai 2013, 09:40

Gracias, also es schaut so aus, wie ich es mir vorgestellt habe :D

Code: Alles auswählen

import numpy as np


t=np.arange(0.0,10.0,0.5)
x=np.sin(t)
y=np.cos(t)



M=np.column_stack((t.T,x.T,y.T))
#print M

header = '{0:9}{1:11}{2:6}{3:10}{4:5}{5:2}'.format(' ', 't', ' ', 'x', ' ', 'y\n')

with open("save.asc","w") as f:
    f.write(header)
    np.savetxt(f,M,fmt="%15.4e")



b=np.genfromtxt("save.asc")
print b
und kommt schön raus:

Code: Alles auswählen

         t                x              y
     0.0000e+00      0.0000e+00      1.0000e+00
     5.0000e-01      4.7943e-01      8.7758e-01
     1.0000e+00      8.4147e-01      5.4030e-01
     1.5000e+00      9.9749e-01      7.0737e-02
     2.0000e+00      9.0930e-01     -4.1615e-01
     2.5000e+00      5.9847e-01     -8.0114e-01
     3.0000e+00      1.4112e-01     -9.8999e-01
     3.5000e+00     -3.5078e-01     -9.3646e-01
     4.0000e+00     -7.5680e-01     -6.5364e-01
     4.5000e+00     -9.7753e-01     -2.1080e-01
     5.0000e+00     -9.5892e-01      2.8366e-01
     5.5000e+00     -7.0554e-01      7.0867e-01
     6.0000e+00     -2.7942e-01      9.6017e-01
     6.5000e+00      2.1512e-01      9.7659e-01
     7.0000e+00      6.5699e-01      7.5390e-01
     7.5000e+00      9.3800e-01      3.4664e-01
     8.0000e+00      9.8936e-01     -1.4550e-01
     8.5000e+00      7.9849e-01     -6.0201e-01
     9.0000e+00      4.1212e-01     -9.1113e-01
     9.5000e+00     -7.5151e-02     -9.9717e-01
Danke euch nochmal an dieser Stelle.


Wegen den Befehlen hab ich hauptsächlich aus Interesse gefragt.

Aber jetzt möchte ich die Datei save.asc wieder einlesen und es soll dann am Schluss so zugewiesen sein, dass steht:

t=1.Spalte
x=2.Spalte
y=3.Spalte

Mit dem Befehl "genfromtxt" liest er mir das im Interpreter so ein:

Code: Alles auswählen

[[      nan       nan       nan]
 [ 0.        0.        1.      ]
 [ 0.5       0.47943   0.87758 ]
 [ 1.        0.84147   0.5403  ]
 [ 1.5       0.99749   0.070737]
 [ 2.        0.9093   -0.41615 ]
 [ 2.5       0.59847  -0.80114 ]
 [ 3.        0.14112  -0.98999 ]
 [ 3.5      -0.35078  -0.93646 ]
 [ 4.       -0.7568   -0.65364 ]
 [ 4.5      -0.97753  -0.2108  ]
 [ 5.       -0.95892   0.28366 ]
 [ 5.5      -0.70554   0.70867 ]
 [ 6.       -0.27942   0.96017 ]
 [ 6.5       0.21512   0.97659 ]
 [ 7.        0.65699   0.7539  ]
 [ 7.5       0.938     0.34664 ]
 [ 8.        0.98936  -0.1455  ]
 [ 8.5       0.79849  -0.60201 ]
 [ 9.        0.41212  -0.91113 ]
 [ 9.5      -0.075151 -0.99717 ]]
sprich, er erkennt t,x,y nicht an.

Ich bastel mal ein bisschen rum, wenn ich häng, mach ich wieder meldung ;)
danke nochmal!
BlackJack

@pynew: Die erste Zeile enthält ja auch keine Zahlen und Typen mischen geht in so einem Array nicht. Liest Du meine Beiträge überhaupt? Ich habe das überlesen der Kopfzeile mit dem `skip_header`-Argument jetzt schon zweimal erwähnt.

Die erste Zeile ist egal, Du wirst den Inhalt dort beim Einlesen nicht verwenden. Die Namen für die Spalten schreibst Du im Quelltext noch mal hin. Die werden nicht auf magische Weise aus der Eingabedatei erzeugt. So etwas will man auch gar nicht haben, denn dann könnten beliebige Dateien beliebige Namen neu binden, die man vielleicht schon für etwas anderes verwendet hat. Da ist Chaos und schwer auffindbare Fehler vorprogrammiert.

Für das verteilen der Spalten auf Namen kann man Tupel-Unpacking und das `unpack`-Argument von `numpy.loadtxt()` oder `numpy.genfromtxt()` verwenden. Die Dokumentation hat ein Beispiel dazu beim `unpack`-Argument.
Antworten