einfache liste in csv 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
Nepo
User
Beiträge: 3
Registriert: Samstag 25. Februar 2012, 18:06

Hallo, ich bin gerade dabei aus einem Textfile Koordinaten rauszulesen. Ich habe es geschafft die Koordinaten in eine Liste zu lesen und nun habe ich eine lange liste mit koordinaten:
[27.237462, 83.345078, 27.217926, 83.342168, 27.23817, 84.072138, 27.24444, 84.103368, 27.211578, 84.08994, 27.21573, 84.092112, 27.23877, 84.144702, 27.249474, 84.161484, 27.235806, 84.144504, 27.209982, 84.129126, 27.167166, 84.09696, 27.244044, 84.158424]
Ich möchte diese nun in eine CSV Datei schreiben, sodass die 27'er Werte in spalte a und die 84'er in spalte b kommen.
Optimal wäre noch spalte a mit breite und b mit laenge zu benennen.

Ich kann auch die 27'er werte in eine separate Liste schreiben und die 84 in eine separate Liste, dann müsste also die csv-Datei aus diesen beiden Listen zusammengestellt werden.

So sieht mein kleines Tool derzeit aus, wobei ich derzeit einfach die liste in die laenge.txt datei schreibe.

Code: Alles auswählen

'''
Created on 11.02.2012

@author: Andreas
'''

import sys
import csv

try:
    d = open('decdeg.txt','r')
except:
    print("not possible")
    sys.exit(0)

koor = []
for line in d:
    line = line.strip()
    laenge = len(line)
    such = "\'"
    anz = line.count(such)
    pos = line.find(such)
    nextpos = line.find(such, pos+1)
    dec = line[pos-6:pos]
    dec = float(dec)
    addec = line[pos-9:pos-7]
    addec = float(addec)
    dnext = line[nextpos-6:nextpos]
    dnext = float(dnext)
    adnext = line[nextpos-9:nextpos-7]
    adnext = float(adnext)
    short = (dec*0.006)+addec
    short2 = (dnext*0.006)+adnext
    koor.append(short)
    koor.append(short2)
    print(addec)
    print(adnext)
        
    
d.close()

print("Koordinaten")
print(koor)

try:
    a = open('laenge.txt','w')
except:
    print("not possible")
    sys.exit(0)


for i in koor:
    a.write(str(i)+ "\n")
Inhalt der Original Textdatei decdeg.txt:

Code: Alles auswählen

858 ft	N 27°39.577'	E083°57.513'
482ft	N 27°36.321'	E083°57.028'
 537ft	N 27°39.695'	 E084°12.023'
514ft 	N 27°40.740' 	E084°17.228'
479ft 	N 27°35.263'	 E084°14.990'
506ft 	N 27°35.955'	 E084°15.352'
615ft 	N27°39.795' 	E084°24.117'
682ft 	N27°41.579'	 E084°26.914'
652ft 	N27°39.301'	 E084°24.084'
546ft 	N27°34.997' 	E084°21.521'
563ft	 N27°27.861' 	E084°16.160'
659 ft 	N 27°40.674'	 E 084°26.404'
Zuletzt geändert von Anonymous am Samstag 25. Februar 2012, 18:23, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
BlackJack

@Nepo: Statt alle Werte nacheinander in einer Liste zu stecken oder beide Spalten in zwei verschiedene Listen, solltest Du alle Werte die in Zeilen gehören in Listen stecken, die dann wiederum in einer Liste stecken. Das ist die Struktur mit der das `csv`-Modul umgehen kann.

Deine Fehlerbehandlung ist keine. Zum einen sollte man kein nacktes ``except`` verwenden, weil das *alle* Ausnahmen betrifft, also zum Beispiel auch wenn Du Dich bei einem Namen vertippst. Dann bekommst Du ein nichtssagendes "not possible" ausgegeben, statt einem hilfreichen Stacktrace der sagt *was* und *wo* genau falsch gelaufen ist.

Dateien sollte man mit der ``with``-Anweisung öffnen. Und Namen sollten in der Regel länger als ein Zeichen sein, keine Abkürzungen sein — solange die nicht allgemein bekannt sind, und beschreiben welche Bedeutung der Wert für das Programm hat.

In der Schleife werden viel zu viele unverständliche Namen an Werte gebunden. Da könnte man sich einiges sparen. Ich glaube es werden auch gar nicht alle Namen im weiteren Verlauf verwendet!?

Bei dem Dateiformat würde ich wohl eher reguläre Ausdrücke verwenden um die Zahlen aus den Zeilen zu extrahieren. Deine fixen Indizes sehen mir nicht sehr robust aus. Die Gradzahl könnte doch zum Beispiel in der zweiten Spalte auch dreistellig werden. Schau Dir mal das `re`-Modul an.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

CSV steht ja für comma-separated-value. Gerade bei Zahlen müsste man noch nicht einmal den Aufwand des CSV-Moduls betreiben und könnte die einfach entsprechend ausgeben. Aber hier mal ein Beispiel für das CSV-Modul, welches zudem einen regulären Ausdruck nutzt, um die Eingabe zu verarbeiten, was zumindest ich für lesbarer halte, als das manuelle Zerteilen der Strings:

Code: Alles auswählen

import re, csv

s = """
858 ft   N 27°39.577'   E083°57.513'
482ft   N 27°36.321'   E083°57.028'
537ft   N 27°39.695'    E084°12.023'
514ft    N 27°40.740'    E084°17.228'
479ft    N 27°35.263'    E084°14.990'
506ft    N 27°35.955'    E084°15.352'
615ft    N27°39.795'    E084°24.117'
682ft    N27°41.579'    E084°26.914'
652ft    N27°39.301'    E084°24.084'
546ft    N27°34.997'    E084°21.521'
563ft    N27°27.861'    E084°16.160'
659 ft    N 27°40.674'    E 084°26.404'
"""

def convert(s):
    a, b = s.split('°')
    return float(a) + float(b) * 0.006

with open("/tmp/out.csv", "wb") as f:
    w = csv.writer(f)
    w.writerow(['a', 'b'])
    for m in re.finditer(r"(\d+)\s*ft\s+N\s*(.*?)'\s+E\s*(.*?)'", s):
        w.writerow([convert(m.group(3)), convert(m.group(2))])
Stefan
Nepo
User
Beiträge: 3
Registriert: Samstag 25. Februar 2012, 18:06

Danke für die Antworten,
ich lerne gerade python und habe mich jetzt in einem 5stunden marathon mit diesen ansätzen beschäftigt und versucht das re modul zu verstehen und eine eigene neue umsetzung an einem minibeispiel probiert, welches mir die einzelnen zahlen ausgibt, die ich dann nur noch verrechnen brauche:
Nochmals vielen dank für die schnellen antworten.
liebe grüße
nepo

import re
s="""
858 ft N 27° 39.577' E083 °57.513'
482ft N 27°36.321' E083°57.028'
"""
"""text = open("decforum.txt")
s = text.read()
text.close()"""


for m in re.finditer(r"(\d+)\s*ft\s*N\s*(\d+).*?(\d*[.]\d*).*?E(\d+).*?(\d*[.]\d*)'", s):
length = len(m.groups())
for i in range(length + 1):
print("Group", i, ":", m.group(i))


""" """
BlackJack

@Nepo: Mit der `groups()`-Methode bekommst Du schon ein Tupel mit den Gruppen. Davon die Länge zu nehmen um dann über die Nummern und die `group()`-Methode noch einmal jede Gruppe einzeln von dem `Match`-Objekt abzufragen ist reichtlich umständlich.
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

Es gibt den Iteratoren „enumerate“, mit dem du einen Counter + das jeweilige Element erhältst:

Code: Alles auswählen

for i, group in enumerate(m.groups()):
    print("Group", i, ":", group)
Für den String „Beispiel“ sähe das so aus:

Code: Alles auswählen

In [2]: tuple(enumerate('Beispiel'))
Out[2]: 
((0, 'B'),
 (1, 'e'),
 (2, 'i'),
 (3, 's'),
 (4, 'p'),
 (5, 'i'),
 (6, 'e'),
 (7, 'l'))
Nepo
User
Beiträge: 3
Registriert: Samstag 25. Februar 2012, 18:06

Ich steige immer tiefer in die Sphären von Python, jetzt wollte ich den Tupel in eine Liste mit Float-Zahlen umwandeln und die einzelnen Zeilen in Unterlisten packen, damit ein export in die csv leichter ist. Vielleicht wäre es auch gut, die einzelnen Zeilen in einzel Listen zu haben, aber da weiss ich auch nicht wie das geht. mein ergebnis sieht nun wie folgt aus:

Code: Alles auswählen

'''
Created on 25.02.2012

@author: Andreas
'''

import re
s="""
858 ft    N 27° 39.577'    E083 °57.513'
482ft    N 27°36.321'    E083°57.028'
"""
"""text = open("decforum.txt")
s = text.read()
text.close()"""

liste = []
for m in re.finditer(r"(\d+)\s*ft\s*N\s*(\d+).*?(\d*[.]\d*).*?E(\d+).*?(\d*[.]\d*)'", s):
    print(m.groups(0))
    a=float(m.group(1))
    b=float(m.group(2))
    c=float(m.group(3))
    d=float(m.group(4))
    e=float(m.group(5))
    f=b+(c*0.006)
    g=d+(e*0.006)
    list2 = []
    list2.append(a)
    list2.append(f)
    list2.append(g)
    liste.append(list2)

print(liste)
Insgesamt macht python sehr viel spass und das ist auch das erstemal, dass ich mich mit programmieren beschäftige.
Naja jetzt geh ich aber schlafen, schon 2 uhr nachts und wochenende, langsam fang ich an mir sorgen zu machen.
also machts gut leute.
webspider
User
Beiträge: 485
Registriert: Sonntag 19. Juni 2011, 13:41

Code: Alles auswählen

list2 = []
list2.append(a)
list2.append(f)
list2.append(g)
liste.append(list2)
ist äquivalent zu

Code: Alles auswählen

liste.append([a, f, g]) # Liste "on-the-fly" erstellt
und

Code: Alles auswählen

a=float(m.group(1))
b=float(m.group(2))
c=float(m.group(3))
d=float(m.group(4))
e=float(m.group(5))
ist äquivalent zu

Code: Alles auswählen

a, b, c, d, e = map(float, m.groups(range(1, 6))) # Unpacking, map, m.groups mit range
Was aber soll das hier sein?

Code: Alles auswählen

"""text = open("decforum.txt")
s = text.read()
text.close()"""
Python behandelt sowas als Docstring, d.h. keiner der Befehle wird jemals ausgeführt. Generell wird für Dateizugriff das with-Statement empfohlen.
BlackJack

Solange keine überflüssigen Gruppen definiert wurden, reicht auch:

Code: Alles auswählen

a, b, c, d, e = map(float, match.groups())
Wobei die Namen `a` bis `e` nicht so toll sind. Da sollte man etwas nehmen, was das verstehen erleichtert.
webspider
User
Beiträge: 485
Registriert: Sonntag 19. Juni 2011, 13:41

Ja, der nächste logische Schritt wäre den regulären Ausdruck so umzuformulieren, dass keine überflüssigen Gruppen mehr definiert werden. Damit Nepo allerdings seinen Code noch halbwegs wiedererkennt, habe ich erstmal nur die offensichtlichsten Verbesserungen gepostet.
Antworten