2012-03-22 22 views
9

Un amigo mío necesita leer muchos datos (alrededor de 18000 conjuntos de datos) que están todos formateados molestamente. Específicamente, se supone que los datos son 8 columnas y ~ 8000 filas de datos, pero en su lugar los datos se entregan en columnas de 7 con la última entrada en la primera columna de la siguiente fila.Python: cómo leer un archivo de datos con un número impar de columnas

Además cada ~ 30 filas solo hay 4 columnas. Esto se debe a que algunos programas en sentido ascendente están remodelando una matriz de 200 x 280 en la matriz 7x8120.

Mi pregunta es esta: ¿cómo podemos leer los datos en una matriz de 8x7000. Mi arsenal habitual de np.loadtxt y np.genfromtxt falla cuando hay un número desigual de columnas.

Tenga en cuenta que el rendimiento es un factor, ya que esto tiene que hacerse para ~ 18000 archivos de datos.

Aquí hay un enlace a un archivo de datos típico: http://users-phys.au.dk/hha07/hk_L1.ref

+0

Para aclarar: cada 24 filas hay una fila de 4 columnas debido al "desbordamiento" continuo de las ocho columnas en cada fila siguiente. ¿Derecha? Cada bloque de 24 * 7 + 4 tiene 200 elementos, que es divisible de manera equitativa por 8. –

+1

Un ejemplo sería muy útil. –

+1

¿Qué le parece si repara el programa original para producir buenos archivos HDF5, o al menos algo menos loco que esto? –

Respuesta

11

Un enfoque aún más fácil me acaba de ocurrir:

with open("hk_L1.ref") as f: 
    data = numpy.array(f.read().split(), dtype=float).reshape(7000, 8) 

Esto lee los datos como una matriz unidimensional primero, ignorando por completo todos los caracteres de nueva línea, y luego darle forma a la forma deseada.

Si bien creo que la tarea será enlazada de I/O de todos modos, este enfoque debería usar poco tiempo de procesador si es que importa.

0

¿Qué tal esto?

data = [] 
curRow = [] 
dataPerRow = 8 
for row in FILE.readlines(): 
    for item in row.split(): 
     if len(curRow) == dataPerRow: 
      data.append(curRow) 
      curRow = [] 
     curRow.Append(item) 

data.append(curRow) 

(ARCHIVO suponiendo que es el archivo de la lectura inicial) A continuación, tiene una lista de listas, que pueden ser utilizados para lo que sea.

1

Se proporcionan he entendido bien (ver mi comentario) se puede dividir su entrada en fichas, y luego procesarlo en bloques de ocho indistintamente:

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 

f = open('filename.ref') 
tokens = f.read().split() 

rows = [] 
for idx, token in enumerate(tokens): 
    if idx % 8 == 0: 
     # this is a new row, use a new list. 
     row = [] 
     rows.append(row) 
    row.append(token) 

# rows is now a list of lists with the desired data. 

Esto ejecuta en menos de 0,2 segundos en mi equipo como es.

Editar: Usado @ sugerencia de SvenMarnach.

+0

¿Por qué estás usando 'shlex' aquí? Un simple 'str.split()' haría el truco. –

+0

@SvenMarnach: Pensé que esto era más fácil ya que presenta un flujo interminable de tokens desde el archivo. Con 'line.split()' Tendría que iterar sobre el archivo yo mismo, haciendo un seguimiento de la compensación actual debido al problema de 8 columnas en 7 que describió OP. O eso o escribir un generador, supongo, pero eso es más o menos para lo que uso aquí el shlex. Si no estoy siguiendo, ¡házmelo saber! –

+0

Simplemente use 'f.read(). Split()', y listo. –

Cuestiones relacionadas