2012-08-13 20 views
12

Estoy tratando de analizar una serie de archivos de texto y guardarlos como archivos CSV usando Python (2.7.3). Todos los archivos de texto tienen un encabezado de 4 líneas que debe ser eliminado. Las líneas de datos tienen varios delimitadores que incluyen "(quote), - (dash),: column y espacio en blanco. Me resultó difícil codificarlo en C++ con todos estos delimitadores diferentes, así que decidí probarlo en Python al escucharlo es relativamente más fácil de hacer en comparación con C/C++.Análisis de archivos de texto con Python

Escribí un código para probarlo en una sola línea de datos y funciona, sin embargo, no pude lograr que funcione para el archivo real. analizando una sola línea Estaba usando el objeto de texto y el método "reemplazar" Parece que mi implementación actual lee el archivo de texto como una lista y no hay un método de reemplazo para el objeto de la lista.

Siendo un novato en Python , Me quedé atascado en este punto. Cualquier entrada sería apreciada!

Gracias!

# 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

Debe adjuntar una copia del archivo que necesita analizar y la salida esperada, de esta forma le será más fácil ayudarlo. –

Respuesta

10

me gustaría utilizar un bucle for para repetir las líneas en el archivo de texto:

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

Si desea leer el archivo línea por línea en lugar de cargar todo el asunto en el inicio de la secuencia de comandos que podría hacer algo como esto:

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

gracias! ¿Cuál sería la mejor manera de saltear las primeras 4 líneas entonces? Para admitir, no pude encontrar la manera de hacerlo, es por eso que decidí leer todo el asunto. ¿Debo escribir el archivo, excepto las primeras 4 líneas en otro archivo para ejecutar el ciclo que tienes arriba? Apuesto que debería haber una manera más fácil sin embargo. EDITAR: oh, espera, creo que te refieres a reemplazar la línea 'txt = data_parser (my_text, reps)' con el ciclo que tienes arriba. – marillion

+0

Ya salteaste las primeras 4 líneas con la línea 'my_text = inputfile.readlines() [4:] ', si prefiere leer el archivo línea por línea y no cargar todo en ram al principio del script, puedo actualizar mi respuesta. –

+0

Disculpa, lo entendí mal en primer lugar (mira mi EDIT), pero gracias, funciona perfectamente. Ahora, estaría muy contento de aprender sobre la forma de "leer línea-analizar-escribir línea (línea por línea)". Tengo algunos archivos de gran tamaño con un tamaño de + 500MB, que pueden estropear las cosas. ¿Podrías actualizar tu respuesta con un segundo ejemplo? – marillion

2

Hay algunas maneras de hacerlo. Una opción sería usar inputfile.read() en lugar de inputfile.readlines() - necesitaría escribir un código separado para quitar las primeras cuatro líneas, pero si desea que el resultado final sea una sola cadena de todos modos, esto podría tener más sentido.

Una segunda opción más sencilla sería volver a unir las cadenas después de dividir las primeras cuatro líneas con my_text = ''.join(my_text). Esto es un poco ineficiente, pero si la velocidad no es una preocupación importante, el código será más simple.

Finalmente, si realmente desea la salida como una lista de cadenas en lugar de una sola cadena, puede simplemente modificar su analizador de datos para iterar sobre la lista. Esa fuerza es como la siguiente:

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

De la respuesta aceptada, parece que su comportamiento deseado es convertir

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 

en

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 

Si eso es correcto, entonces pienso algo así como

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) 

sería un poco más simple que reps cosas.

+0

Intenté usar el módulo csv antes de encontrar el bit 'reps', pero encontré la documentación un poco confusa. Tu ejemplo lo deja muy claro. Voy a intentar esto, solo por el bien de aprender también. 1. ¿eliminas las comillas en el archivo de texto por 'quoting = False'? 2. podrías verificar mi entendimiento? La línea 'date' en el código divide primero la parte de la fecha y se convierte en una lista en sí misma,' day' y 'time' se dividen a continuación, y el resto de la línea se agrega al' day' y 'time'. No estoy seguro de cómo agrega automáticamente comas, en su línea 'newline = day + time + line [1]'. Hmm ... – marillion

+0

@marillon: (1) Sí, hay muchas opciones de presupuesto diferentes. Creo que es un poco extraño deshacerse de todos ellos, en realidad, pero tal vez lo necesites por alguna razón. (2) Sip. Las comas no se agregan en 'newline', eso es solo una lista. 'writerow' es el método' writer' que agrega comas a la cadena de salida (o pestañas o cualquier otro delimitador que quisiéramos) y manejaba las comillas si queríamos eso. – DSM

+0

Ok, creo que lo tengo. Además, nunca necesitó analizar la porción de datos de la línea, ya que ya estaba separada por comas. Buena información, muchas gracias! – marillion

Cuestiones relacionadas