2011-08-16 27 views
8

Tengo un archivo grande (100 millones de líneas de valores separados por tabuladores, aproximadamente 1,5 GB de tamaño). ¿Cuál es la forma más rápida de ordenar esto en función de uno de los campos?ordenando datos de texto grandes

He intentado la colmena. Me gustaría ver si esto se puede hacer más rápido usando Python.

Respuesta

16

¿Ha considerado utilizar el programa * nix sort? en términos brutos, probablemente sea más rápido que la mayoría de los scripts de Python.

Uso -t $'\t' para especificar que es separado por tabuladores, -k n para especificar el campo, donde n es el número de campo, y -o outputfile si desea enviar el resultado a un archivo nuevo. Ejemplo:

sort -t $'\t' -k 4 -o sorted.txt input.txt 

clasificará input.txt en su cuarto campo, y enviar el resultado a sorted.txt

+0

el comando de ordenamiento unix es una herramienta muy poderosa. Puede controlar el formato del campo para ordenar (numérico, fecha, etc.) y la cantidad de memoria que el programa puede asignar, realizando una división + combinación si es necesario. –

+0

alex ¿Puedes dar un ejemplo? El programa de clasificación en sí mismo lleva bastante tiempo ... del orden de 40 minutos. Esto puede tener algo que ver con la asignación de memoria o el disco IO. No estoy seguro de cómo saber cuál es el cuello de botella, pero supongo que su sugerencia puede ser útil. – fodon

+1

un error en la solución anterior: para usar solo el segundo campo, uno necesita -k 2,2 ... por lo que no está indexado en cero (al menos no en la versión de Kubuntu 11.04). – fodon

1

Me almacenar el archivo en una buena base de datos relacional, índice en el campo tiene interés en conocer y luego lee los artículos pedidos

7

usted quiere construir un índice en memoria para el archivo:

  1. crear una lista vacía
  2. open el archivo
  3. leer línea por línea (usando f.readline(), y almacenar en la lista una tupla que consiste en el valor sobre el que desea ordenar (extraído con line.split('\t').strip()) y el desplazamiento de la línea en el archivo (que puede obtener llamando al f.tell() antes de llamar al f.readline())
  4. close el archivo
  5. sort la lista

continuación para imprimir el archivo ordenado, vuelva a abrir el archivo y para cada elemento de la lista, utilice f.seek(offset) para mover el puntero del archivo al principio de la línea, f.readline() para leer la línea y print la línea.

Optimización: es posible que desee almacenar la longitud de la línea en la lista, para que pueda usar f.read(length) en la fase de impresión.

Código de la muestra (optimizado para facilitar la lectura, no la velocidad):

def build_index(filename, sort_col): 
    index = [] 
    f = open(filename) 
    while True: 
     offset = f.tell() 
     line = f.readline() 
     if not line: 
      break 
     length = len(line) 
     col = line.split('\t')[sort_col].strip() 
     index.append((col, offset, length)) 
    f.close() 
    index.sort() 
    return index 

def print_sorted(filename, col_sort): 
    index = build_index(filename, col_sort) 
    f = open(filename) 
    for col, offset, length in index: 
     f.seek(offset) 
     print f.read(length).rstrip('\n') 

if __name__ == '__main__': 
    filename = 'somefile.txt' 
    sort_col = 2 
    print_sorted(filename, sort_col) 
3

divide en archivos que se pueden clasificar en la memoria. Clasifica cada archivo en la memoria. A continuación, combine los archivos resultantes.

Combina leyendo una parte de cada uno de los archivos que se fusionarán. La misma cantidad de cada archivo deja suficiente espacio en la memoria para el resultado fusionado. Una vez que se fusionó guardar esto. Repite la adición de bloques de datos combinados en el archivo.

Esto minimiza el archivo de E/S y mueve el archivo en el disco.

Cuestiones relacionadas