2012-03-28 26 views
7

Desidero salvare un array 2D in un file CSV con informazioni di "intestazione" di riga e colonna (come una tabella). So che potrei usare l'argomento header su numpy.savetxt per salvare i nomi delle colonne, ma c'è un modo semplice per includere anche qualche altro array (o lista) come prima colonna di dati (come i titoli delle righe)?Python/Numpy - Salva array con colonne e titoli di riga

Di seguito è riportato un esempio di come lo faccio attualmente. C'è un modo migliore per includere quei titoli di riga, forse qualche trucco con salvataggio di cui non sono a conoscenza?

import csv 
import numpy as np 

data = np.arange(12).reshape(3,4) 
# Add a '' for the first column because the row titles go there... 
cols = ['', 'col1', 'col2', 'col3', 'col4'] 
rows = ['row1', 'row2', 'row3'] 

with open('test.csv', 'wb') as f: 
    writer = csv.writer(f) 
    writer.writerow(cols) 
    for row_title, data_row in zip(rows, data): 
     writer.writerow([row_title] + data_row.tolist()) 

risposta

6

Forse si preferisce fare qualcosa di simile:

# Column of row titles 
rows = np.array(['row1', 'row2', 'row3'], dtype='|S20')[:, np.newaxis] 
with open('test.csv', 'w') as f: 
    np.savetxt(f, np.hstack((rows, data)), delimiter=', ', fmt='%s') 

Questo è implicitamente conversione data ad un array di stringhe, e dura circa 200 ms per ogni milione di articoli nel mio computer.

Il dtype '|S20' significa stringhe di venti caratteri. Se è troppo basso, i numeri avranno tagliato:

>>> np.asarray([123], dtype='|S2') 
array(['12'], 
    dtype='|S2') 

Un'altra opzione, che dal mio test limitato è più lento, ma ti dà molto più controllo e non ha il problema di taglio sarebbe utilizzando np.char.mod, come

# Column of row titles 
rows = np.array(['row1', 'row2', 'row3'])[:, np.newaxis] 
str_data = np.char.mod("%10.6f", data) 
with open('test.csv', 'w') as f: 
    np.savetxt(f, np.hstack((rows, str_data)), delimiter=', ', fmt='%s') 
+0

l'uso di hstack deve ricreare la matrice nella memoria, giusto? Quindi, se i dati sono molto grandi, dobbiamo riassegnare nuovamente quella memoria. Per la mia specifica applicazione, è improbabile che ci sia qualche problema reale, ma solo un punto che meriti di essere menzionato. E probabilmente non c'è alcun modo per aggirare questo. Sembra che qualcosa che Savetxt dovrebbe implementare internamente, anche se deve fare una soluzione simile alla mia (ma nel codice C sottostante). –

+0

Sì, hai ragione. Penso che forse tutto questo overhead potrebbe essere evitato con un array di record, e usando il fatto che fmt accetta una lista di operatori di formattazione, come 'fmt = ['% s', '% f', ...]', ma Non ho familiarità con loro, e quindi questa è solo una supposizione. – jorgeca

+0

Ya, ho preso in considerazione anche un array di record. Penso che tu abbia ragione, che potrebbe essere usato ... ma speravo di evitarli ... Immagino che sceglierò solo quello che sembra essere il minore dei due mali. –