2011-08-16 11 views
8

Ho un file di grandi dimensioni (100 milioni di righe di valori separati da tabulazione - circa 1,5 GB di dimensione). Qual è il modo più rapido per ordinare questo in base a uno dei campi?ordinamento di grandi dati di testo

Ho provato l'alveare. Mi piacerebbe vedere se questo può essere fatto più velocemente usando python.

risposta

16

Avete considerato l'utilizzo del programma * nix sort? in termini non elaborati, sarà probabilmente più veloce della maggior parte degli script Python.

Usa -t $'\t' per specificare che si tratta di separato da tabulazioni, -k n per specificare il campo, dove n è il numero di campo, e -o outputfile se si desidera emettere il risultato in un nuovo file. Esempio:

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

ordinerà input.txt sul suo quarto campo, e l'uscita il risultato di sorted.txt

+0

il comando unix sort è davvero uno strumento molto potente. È possibile controllare il formato del campo per ordinare (numerico, data, ecc.) E la quantità di memoria che il programma può allocare, eseguendo un ordinamento split + merge se necessario. –

+0

alex puoi fare un esempio? Il programma di ordinamento da solo richiede molto tempo ... dell'ordine di 40 minuti. Questo potrebbe avere qualcosa a che fare con l'allocazione di memoria o l'I/O del disco. Non sono sicuro di capire quale sia il collo di bottiglia, ma suppongo che il tuo suggerimento possa essere utile. – fodon

+1

un errore nella soluzione sopra: per usare solo il 2 ° campo, uno ha bisogno di -k 2,2 ... quindi non è indicizzato a zero (almeno non sulla versione di ordinamento di Kubuntu 11.04). – fodon

1

avrei memorizzare il file in un buon database relazionale, l'indice sul campo siete interessati e poi leggi gli articoli ordinati.

7

si vuole costruire un indice in memoria per il file:

  1. creare una lista vuota
  2. open il file
  3. leggerlo riga per riga (utilizzando f.readline(), e conservare in lista una tupla costituita dal valore su cui si desidera ordinare (estratto con line.split('\t').strip()) e l'offset della riga nel file (che è possibile ottenere chiamando f.tell() prima di chiamare f.readline())
  4. close il file
  5. sort lista

Poi per stampare il file ordinato, riaprire il file e per ogni elemento della vostra lista, utilizzare f.seek(offset) per spostare il puntatore del file all'inizio della riga, f.readline() a leggere la linea e print la linea.

Ottimizzazione: è possibile memorizzare la lunghezza della linea nell'elenco, in modo da poter utilizzare f.read(length) nella fase di stampa.

codice di esempio (ottimizzato per leggibilità, non di velocità):

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

contempla file che possono essere ordinati in memoria. Ordina ogni file in memoria. Quindi unire i file risultanti.

Unisci leggendo una porzione di ciascuno dei file da unire. La stessa quantità da ogni file che lascia abbastanza spazio in memoria per il risultato unito. Una volta uniti salvando questo. Ripetizione dell'aggiunta di blocchi di dati uniti nel file.

Ciò minimizza il file i/o e sposta il file sul disco.