Python: ¿Cómo cargar la columna desde tablas csv multibloque?

Estoy trabajando en un programa apto para datos SIP en este momento. Desafortunadamente, los datos vienen dentro de una tabla csv con la siguiente estructura:

       f;      Abs(Zm);     Std(Abs);      Phi(Zm);     Std(Phi);       Re(Zm);       Im(Zm);     Time [s]
1.0000000e-001;    7712.6262;       0.0247;    -0.003774;     0.000001;    7712.5713;     -29.1074;   3418623040
2.0000000e-001;    7712.4351;       0.0030;    -0.007543;     0.000001;    7712.2157;     -58.1732;   3418623056
5.0000000e-001;    7710.8455;       0.0094;    -0.018837;     0.000002;    7709.4775;    -145.2434;   3418623063
1.0000000e+000;    7705.3763;       0.0098;    -0.037637;     0.000000;    7699.9195;    -289.9395;   3418623067
2.0000000e+000;    7683.8120;       0.0241;    -0.075058;     0.000001;    7662.1778;    -576.1935;   3418623069
5.0000000e+000;    7539.7945;       0.0080;    -0.184724;     0.000002;    7411.5201;   -1384.8720;   3418623071
1.0000000e+001;    7088.6894;       0.0060;    -0.351521;     0.000001;    6655.2169;   -2440.8206;   3418623072


         f;     Abs(Z12);     Phi(Z12);     Abs(Z34);     Phi(Z34);     Abs(Z14);     Phi(Z14);     Time [s]
1.0000000e-001;       1.7821;     3.139014;       0.2545;    -3.141592;    7710.5896;    -0.003774;   3418623040
2.0000000e-001;       1.7850;     3.133381;       0.2572;    -3.126220;    7710.3930;    -0.007543;   3418623056
5.0000000e-001;       1.7755;     3.121223;       0.2514;    -3.133763;    7708.8186;    -0.018838;   3418623063
1.0000000e+000;       1.7683;     3.100815;       0.2503;     3.139466;    7703.3580;    -0.037638;   3418623067
2.0000000e+000;       1.8091;     3.058834;       0.2538;    -3.123705;    7681.7502;    -0.075060;   3418623069
5.0000000e+000;       1.5547;     2.943611;       0.2398;    -3.136317;    7538.0045;    -0.184727;   3418623071

Estoy usando una rutina numpy.loadtxt() para recopilar los datos de la tabla de esta manera:

def load_datafile(filename):
try:
     x_data, y_data = numpy.loadtxt(filename , unpack=True, usecols=(0,1),) 
except IOError:
    print('There was an error opening the file: {0}'.format(filename))
    x_data=[]
    y_data=[]
return x_data, y_data

Sé que no hay más identificadores para usar un bloque específico de una tabla en el comando loadtxt(). ¿Pero hay una solución práctica?

De lo contrario, ¿hay un script simple que pueda reorganizar el archivo de entrada csv en columnas de un solo bloque?

¡Gracias por adelantado! Saludos, Gunnar

preguntado el 03 de mayo de 12 a las 08:05

¿Podría aclarar qué quiere decir con un "bloque"? -

sus datos de ejemplo tienen diferentes columnas en cada bloque y el tamaño del bloque es diferente de un bloque a otro (7 filas en el primero, 6 en el segundo). ¿Es eso cierto? ¿Necesita leer los datos de cada bloque y cada columna? -

2 Respuestas

Primero podría dividir los datos de entrada en bloques, luego usar loadtxt o genfromtxt (prefiero este, porque tiene una opción para leer encabezados).

from numpy import genfromtxt
from StringIO import StringIO

def read_by_block(filename):
    blocks = []
    data = open(filename).read()
    for blk in data.split('\n\n'): # we assume that blocks are separated by two newlines
        blocks.append(genfromtxt(StringIO(blk), delimiter=';', names=True))
    return blocks

data = read_by_block('data.txt')

print data[0].dtype.names # print fields for first block
print data[0]['StdPhi'] # print column 'Std(Phi)' in 1st block

contestado el 03 de mayo de 12 a las 13:05

Gracias por la idea de genfromtxt(). Después de manipular el estilo de nueva línea en mi tabla csv, funcionó muy bien. - usuario1371788

Si desea más flexibilidad con respecto al estilo de nueva línea, también puede dividir según la expresión regular: re.split. - François

Suponiendo que, al igual que la entrada, siempre hay un par de saltos de línea vacíos, este pequeño script debería devolver un montón de objetos de archivo:

def parseMultiblockCSV(filename):
    original = open(filename, "r")
    newlines = 0
    block = 0
    current = open(filename + "." + str(block), "w")
    for line in original:
        if line == "":
            newlines += 1
        if newlines >= 2:
            current.close()
            block += 1
            current = open(filename + "." + str(block), "w")
        current.write(line)
    current.close()
    files = []
    for n in range(block + 1):
        files.append(open(filename + "." + str(n)))
    return files

Si luego los necesitaba a ambos en la misma tabla, supongo que tiene una función para cargar varios archivos en una sola tabla. De lo contrario:

def combineCSVFiles(files, output):
    if len(files) == 1:
        return files[0]
    start = file[0]
    files = file[1:]
    out = open(output, "w")
    for line in start:
        out.write(line)
    for input in files:
        first = false
        for line in input:
        if not first:
            first = true
            continue
        out.write(line)
    out.close()
    return open(output, "r")

Eso debería devolver un objeto de archivo que contenga los contenidos concatenados de los objetos de archivo dados, ignorando la primera línea de encabezado de cualquier cosa que no sea el primer archivo.

contestado el 03 de mayo de 12 a las 08:05

Creo que las columnas son diferentes de un bloque a otro, por lo que su respuesta no maneja eso. ¿O me pierdo algo? - bmu

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.