2012-08-13 4 views
12

Ich versuche, eine Reihe von Textdateien zu analysieren und speichern sie als CSV-Dateien mit Python (2.7.3). Alle Textdateien haben eine 4 Zeilen lange Kopfzeile, die entfernt werden muss. Die Datenzeilen haben verschiedene Begrenzer einschließlich "(quote), - (strich),: spalte und Leerzeichen. Ich fand es ein Schmerz, es in C++ mit all diesen verschiedenen Begrenzern zu codieren, also habe ich beschlossen, es in Python zu versuchen, es zu hören ist im Vergleich zu C/C++ relativ einfacher zu machen.Textdateianalyse mit Python

Ich schrieb ein Stück Code, um es für eine einzelne Zeile von Daten zu testen, und es funktioniert, aber ich konnte es nicht schaffen, dass es für die eigentliche Datei funktioniert Parsing einer einzelnen Zeile Ich habe das Textobjekt und "Ersetzen" -Methode. Es sieht aus wie meine aktuelle Implementierung liest die Textdatei als eine Liste, und es gibt keine Methode zum Ersetzen des Listenobjekts.

Als Novize in Python Ich steckte an diesem Punkt fest. Irgendwelche Eingaben würden geschätzt!

Danke!

# function for parsing the data 
def data_parser(text, dic): 
for i, j in dic.iteritems(): 
    text = text.replace(i,j) 
return text 

# open input/output files 

inputfile = open('test.dat') 
outputfile = open('test.csv', 'w') 

my_text = inputfile.readlines()[4:] #reads to whole text file, skipping first 4 lines 


# sample text string, just for demonstration to let you know how the data looks like 
# my_text = '"2012-06-23 03:09:13.23",4323584,-1.911224,-0.4657288,-0.1166382,-0.24823,0.256485,"NAN",-0.3489428,-0.130449,-0.2440527,-0.2942413,0.04944348,0.4337797,-1.105218,-1.201882,-0.5962594,-0.586636' 

# dictionary definition 0-, 1- etc. are there to parse the date block delimited with dashes, and make sure the negative numbers are not effected 
reps = {'"NAN"':'NAN', '"':'', '0-':'0,','1-':'1,','2-':'2,','3-':'3,','4-':'4,','5-':'5,','6-':'6,','7-':'7,','8-':'8,','9-':'9,', ' ':',', ':':',' } 

txt = data_parser(my_text, reps) 
outputfile.writelines(txt) 

inputfile.close() 
outputfile.close() 
+2

Sie sollten eine Kopie der Datei, die Sie analysieren müssen, und die erwartete Ausgabe anhängen, so wird es einfacher, Ihnen zu helfen. –

Antwort

10

Ich würde eine for-Schleife über die Zeilen in der Textdatei iterieren:

for line in my_text: 
    outputfile.writelines(data_parser(line, reps)) 

Wenn Sie die Datei Zeile-für-Zeile statt Laden die ganze Sache an die lesen wollen Start des Skripts Sie könnten etwas tun wie folgt:

inputfile = open('test.dat') 
outputfile = open('test.csv', 'w') 

# sample text string, just for demonstration to let you know how the data looks like 
# my_text = '"2012-06-23 03:09:13.23",4323584,-1.911224,-0.4657288,-0.1166382,-0.24823,0.256485,"NAN",-0.3489428,-0.130449,-0.2440527,-0.2942413,0.04944348,0.4337797,-1.105218,-1.201882,-0.5962594,-0.586636' 

# dictionary definition 0-, 1- etc. are there to parse the date block delimited with dashes, and make sure the negative numbers are not effected 
reps = {'"NAN"':'NAN', '"':'', '0-':'0,','1-':'1,','2-':'2,','3-':'3,','4-':'4,','5-':'5,','6-':'6,','7-':'7,','8-':'8,','9-':'9,', ' ':',', ':':',' } 

for i in range(4): inputfile.next() # skip first four lines 
for line in inputfile: 
    outputfile.writelines(data_parser(line, reps)) 

inputfile.close() 
outputfile.close() 
+0

danke! Was wäre der beste Weg, die ersten 4 Zeilen zu überspringen? Zugegeben, ich konnte keinen Weg finden, das zu tun, deshalb beschloss ich, die ganze Sache zu lesen. Soll ich die Datei mit Ausnahme der ersten 4 Zeilen in eine andere Datei schreiben, um die oben genannte Schleife auszuführen? Ich wette, dass es einen einfacheren Weg geben sollte. EDIT: Oh, warte, ich denke du meinst die Zeile 'txt = data_parser (my_text, reps)' mit der Schleife, die du oben hast, zu ersetzen. – marillion

+0

Sie haben die ersten 4 Zeilen bereits mit der Zeile 'my_text = inputfile 'übersprungen.readlines() [4:] ', wenn du lieber die Datei Zeile für Zeile lesen würdest und die ganze Sache nicht zu Beginn des Skripts in Ram laden würdest, kann ich meine Antwort aktualisieren. –

+0

Sorry, ich habe es falsch verstanden (siehe meine EDIT oben), aber danke, es funktioniert perfekt !!! Nun wäre ich sehr froh über die Art und Weise, Zeilen zu lesen, zu schreiben und Zeilen zu schreiben (line-by-line). Ich habe einige Dateien große Datei mit einer Größe von + 500MB, die Dinge vermasseln können. Könnten Sie Ihre Antwort mit einem zweiten Beispiel aktualisieren? – marillion

2

Es gibt ein paar Möglichkeiten, um darüber zu gehen. Eine Option wäre, inputfile.read() anstelle von inputfile.readlines() zu verwenden - Sie müssten separaten Code schreiben, um die ersten vier Zeilen zu streichen, aber wenn Sie die endgültige Ausgabe als eine einzelne Zeichenfolge sowieso wollen, könnte dies am sinnvollsten sein.

Eine zweite, einfachere Option wäre, die Strings nach dem Striping der ersten vier Zeilen mit my_text = ''.join(my_text) wieder zu verbinden. Dies ist ein wenig ineffizient, aber wenn die Geschwindigkeit keine große Rolle spielt, wird der Code am einfachsten sein.

Schließlich, wenn Sie tatsächlich die Ausgabe als eine Liste von Zeichenfolgen anstelle einer einzelnen Zeichenfolge möchten, können Sie nur Ihren Datenparser ändern, um über die Liste zu iterieren. Das könnte in etwa so aussieht:

def data_parser(lines, dic): 
    for i, j in dic.iteritems(): 
     for (k, line) in enumerate(lines): 
      lines[k] = line.replace(i, j) 
    return lines 
10

Von der Antwort akzeptiert, es sieht aus wie Ihr gewünschtes Verhalten

skip 0 
skip 1 
skip 2 
skip 3 
"2012-06-23 03:09:13.23",4323584,-1.911224,-0.4657288,-0.1166382,-0.24823,0.256485,"NAN",-0.3489428,-0.130449,-0.2440527,-0.2942413,0.04944348,0.4337797,-1.105218,-1.201882,-0.5962594,-0.586636 

in

2012,06,23,03,09,13.23,4323584,-1.911224,-0.4657288,-0.1166382,-0.24823,0.256485,NAN,-0.3489428,-0.130449,-0.2440527,-0.2942413,0.04944348,0.4337797,-1.105218,-1.201882,-0.5962594,-0.586636 

einzuschalten ist, wenn das stimmt, dann denke ich, etwas wie

import csv 

with open("test.dat", "rb") as infile, open("test.csv", "wb") as outfile: 
    reader = csv.reader(infile) 
    writer = csv.writer(outfile, quoting=False) 
    for i, line in enumerate(reader): 
     if i < 4: continue 
     date = line[0].split() 
     day = date[0].split('-') 
     time = date[1].split(':') 
     newline = day + time + line[1:] 
     writer.writerow(newline) 

wäre ein wenig einfacher als die reps Sachen.

+0

Ich habe versucht, das csv-Modul zu verwenden, bevor ich mit dem 'reps'-Bit angefangen habe, aber ich fand die Dokumentation ein wenig verwirrend. Ihr Beispiel macht es deutlich. Ich werde es versuchen, nur um zu lernen. 1. Eliminieren Sie Anführungszeichen in der Textdatei, indem Sie "= Falsch" angeben? 2. Könnten Sie mein Verständnis überprüfen? Die "Datum" -Zeile im Code teilt den Datumsteil zuerst auf und wird selbst zu einer Liste, "Tag" und "Zeit" werden als nächstes aufgeteilt, und der Rest der Zeile wird an "Tag" und "Zeit" angehängt. Ich bin mir nicht sicher, wie es automatisch Kommas hinzufügt, in Ihrer Linie "newline = Tag + Zeit + Linie [1]". Hmm ... – marillion

+0

@marillon: (1) Ja, es gibt viele verschiedene Angebotsoptionen. Ich denke, es ist etwas seltsam, sie alle loszuwerden, aber vielleicht brauchen Sie das aus irgendeinem Grund. (2) Ja. Kommas werden nicht in 'newline' hinzugefügt - das ist nur eine Liste. 'Writerow' ist die 'Writer'-Methode, die Kommas zu der Ausgabezeichenfolge (oder Tabulatoren oder irgendeinem anderen Trennzeichen, das wir wollten) hinzufügt und das Zitieren übernehmen würde, wenn wir das wollten. – DSM

+0

Ok, ich glaube, ich habe es verstanden. Außerdem mussten Sie den Datenteil der Zeile überhaupt nicht analysieren, da er bereits durch Kommas getrennt war. Gute Information, vielen Dank! – marillion