2010-09-10 17 views
79

In un'altra domanda, altri utenti hanno offerto aiuto se potevo fornire l'array con cui avevo problemi. Tuttavia, non riesco nemmeno a eseguire un'operazione di I/O di base, come scrivere un array su un file.Come scrivere una matrice multidimensionale in un file di testo?

Qualcuno può spiegare che tipo di ciclo avrei bisogno di scrivere un array numpy 4x11x14 da archiviare?

Questo array consiste di quattro array 11 x 14, quindi dovrei formattarlo con una nuova riga di comando, per facilitare la lettura del file su altri.

Modifica: Così ho provato la funzione numpy.savetxt. Stranamente, dà il seguente errore:

TypeError: float argument required, not numpy.ndarray 

Presumo che questo è perché la funzione non funziona con array multidimensionali? Qualche soluzione come vorrei in un file?

+0

scusa, rileggi la tua domanda dopo aver postato la mia risposta, e sospetto che non soddisfi le tue esigenze - se così non fosse, rispediscimi e posterò un'alternativa. (È bello vederti in questa parte dell'ex quadrilogia!) –

+0

In realtà - sembra che la risposta di Joe Kington dovrebbe funzionare per te. –

risposta

149

Se si desidera scriverlo su disco in modo che sia facile da leggere di nuovo come una matrice numpy, esaminare numpy.save. Il decapaggio funzionerà bene, ma è meno efficiente per i grandi array (che non sono i tuoi, quindi o è perfettamente a posto).

Se si desidera che sia leggibile dall'uomo, esaminare numpy.savetxt.

Edit: Così, sembra che savetxt non è così grande opzione per array con dimensioni> 2 ... Ma solo per disegnare tutto fuori è pieno conclusione:

Ho appena realizzato che numpy.savetxt indurimenti su ndarrays con più di 2 dimensioni ... Ciò è probabilmente dovuto alla progettazione, poiché non esiste un modo intrinsecamente definito per indicare dimensioni aggiuntive in un file di testo.

E.g. Questo (una matrice 2D) funziona bene

import numpy as np 
x = np.arange(20).reshape((4,5)) 
np.savetxt('test.txt', x) 

Mentre la stessa cosa avrebbe fallito (con un errore piuttosto uninformative: TypeError: float argument required, not numpy.ndarray) per un array 3D:

import numpy as np 
x = np.arange(200).reshape((4,5,10)) 
np.savetxt('test.txt', x) 

Una soluzione è solo per rompere il 3D (o superiore) array in sezioni 2D. Per esempio.

x = np.arange(200).reshape((4,5,10)) 
with file('test.txt', 'w') as outfile: 
    for slice_2d in x: 
     np.savetxt(outfile, slice_2d) 

Tuttavia, il nostro obiettivo è quello di essere chiaramente leggibile, pur essendo facilmente riletti con numpy.loadtxt. Pertanto, possiamo essere un po 'più prolissi e differenziare le sezioni utilizzando le linee commentate. Per impostazione predefinita, numpy.loadtxt ignorerà qualsiasi riga che inizia con # (o qualsiasi carattere specificato dal valore comments kwarg). (Questo sembra più dettagliato di quanto non sia in realtà ...)

import numpy as np 

# Generate some test data 
data = np.arange(200).reshape((4,5,10)) 

# Write the array to disk 
with file('test.txt', 'w') as outfile: 
    # I'm writing a header here just for the sake of readability 
    # Any line starting with "#" will be ignored by numpy.loadtxt 
    outfile.write('# Array shape: {0}\n'.format(data.shape)) 

    # Iterating through a ndimensional array produces slices along 
    # the last axis. This is equivalent to data[i,:,:] in this case 
    for data_slice in data: 

     # The formatting string indicates that I'm writing out 
     # the values in left-justified columns 7 characters in width 
     # with 2 decimal places. 
     np.savetxt(outfile, data_slice, fmt='%-7.2f') 

     # Writing out a break to indicate different slices... 
     outfile.write('# New slice\n') 

Questo produce:

# Array shape: (4, 5, 10) 
0.00 1.00 2.00 3.00 4.00 5.00 6.00 7.00 8.00 9.00 
10.00 11.00 12.00 13.00 14.00 15.00 16.00 17.00 18.00 19.00 
20.00 21.00 22.00 23.00 24.00 25.00 26.00 27.00 28.00 29.00 
30.00 31.00 32.00 33.00 34.00 35.00 36.00 37.00 38.00 39.00 
40.00 41.00 42.00 43.00 44.00 45.00 46.00 47.00 48.00 49.00 
# New slice 
50.00 51.00 52.00 53.00 54.00 55.00 56.00 57.00 58.00 59.00 
60.00 61.00 62.00 63.00 64.00 65.00 66.00 67.00 68.00 69.00 
70.00 71.00 72.00 73.00 74.00 75.00 76.00 77.00 78.00 79.00 
80.00 81.00 82.00 83.00 84.00 85.00 86.00 87.00 88.00 89.00 
90.00 91.00 92.00 93.00 94.00 95.00 96.00 97.00 98.00 99.00 
# New slice 
100.00 101.00 102.00 103.00 104.00 105.00 106.00 107.00 108.00 109.00 
110.00 111.00 112.00 113.00 114.00 115.00 116.00 117.00 118.00 119.00 
120.00 121.00 122.00 123.00 124.00 125.00 126.00 127.00 128.00 129.00 
130.00 131.00 132.00 133.00 134.00 135.00 136.00 137.00 138.00 139.00 
140.00 141.00 142.00 143.00 144.00 145.00 146.00 147.00 148.00 149.00 
# New slice 
150.00 151.00 152.00 153.00 154.00 155.00 156.00 157.00 158.00 159.00 
160.00 161.00 162.00 163.00 164.00 165.00 166.00 167.00 168.00 169.00 
170.00 171.00 172.00 173.00 174.00 175.00 176.00 177.00 178.00 179.00 
180.00 181.00 182.00 183.00 184.00 185.00 186.00 187.00 188.00 189.00 
190.00 191.00 192.00 193.00 194.00 195.00 196.00 197.00 198.00 199.00 
# New slice 

lettura indietro in è molto semplice, a patto che noi conosciamo la forma della matrice originale. Possiamo solo fare numpy.loadtxt('test.txt').reshape((4,5,10)). A titolo di esempio (È possibile farlo in una sola riga, sto solo essere dettagliato per chiarire le cose):

# Read the array from disk 
new_data = np.loadtxt('test.txt') 

# Note that this returned a 2D array! 
print new_data.shape 

# However, going back to 3D is easy if we know the 
# original shape of the array 
new_data = new_data.reshape((4,5,10)) 

# Just to check that they're the same... 
assert np.all(new_data == data) 
+2

+1 da me, vedere anche 'numpy.loadtxt' (http://docs.scipy.org/doc/numpy/reference/generated/numpy.loadtxt. html) –

+0

Anche se è leggibile perché il testo è molto utile, se riesci a formattare la tua risposta con un piccolo esempio di codice, accetterò la tua risposta :-) –

+0

Devo prendere l'autobus, ma aggiungo un esempio di codice non appena arrivo ... Grazie! –

22

Non sono sicuro che questo soddisfi le tue esigenze, dato che penso che tu sia interessato a rendere il file leggibile dalle persone, ma se questo non è un problema primario, solo pickle.

Per salvarlo:

import pickle 

my_data = {'a': [1, 2.0, 3, 4+6j], 
      'b': ('string', u'Unicode string'), 
      'c': None} 
output = open('data.pkl', 'wb') 
pickle.dump(data1, output) 
output.close() 

di leggerlo di nuovo:

import pprint, pickle 

pkl_file = open('data.pkl', 'rb') 

data1 = pickle.load(pkl_file) 
pprint.pprint(data1) 

pkl_file.close() 
+0

@ badbod99 - perché la risposta di Joe Kington è migliore della mia :) –

1

Si può semplicemente attraversare l'array in tre cicli nidificati e scrivere i loro valori al file. Per la lettura, è sufficiente utilizzare la stessa esatta struttura del ciclo. Otterrai i valori esattamente nell'ordine giusto per riempire nuovamente gli array correttamente.

7

Se don' Ho bisogno di un output leggibile dall'uomo, un'altra opzione che potresti non fare ry è quello di salvare l'array come file MATLAB .mat, che è un array strutturato. Disprezzo MATLAB, ma il fatto di poter leggere e scrivere uno .mat in pochissime righe è conveniente.

A differenza di risposta di Joe Kington, il vantaggio di questo è che si non c'è bisogno di conoscere la forma originale dei dati nel file .mat, vale a dire non c'è bisogno di rimodellare dopo aver letto in. E, a differenza utilizzando pickle, un file .mat può essere letto da MATLAB e probabilmente anche da altri programmi/lingue.

Ecco un esempio:

import numpy as np 
import scipy.io 

# Some test data 
x = np.arange(200).reshape((4,5,10)) 

# Specify the filename of the .mat file 
matfile = 'test_mat.mat' 

# Write the array to the mat file. For this to work, the array must be the value 
# corresponding to a key name of your choice in a dictionary 
scipy.io.savemat(matfile, mdict={'out': x}, oned_as='row') 

# For the above line, I specified the kwarg oned_as since python (2.7 with 
# numpy 1.6.1) throws a FutureWarning. Here, this isn't really necessary 
# since oned_as is a kwarg for dealing with 1-D arrays. 

# Now load in the data from the .mat that was just saved 
matdata = scipy.io.loadmat(matfile) 

# And just to check if the data is the same: 
assert np.all(x == matdata['out']) 

Se si dimentica la chiave che la matrice è chiamato nel file .mat, si può sempre fare:

print matdata.keys() 

E naturalmente è possibile memorizzare molti matrici che utilizzano molte più chiavi.

Quindi sì - non sarà leggibile con i tuoi occhi, ma prende solo 2 righe per scrivere e leggere i dati, che penso sia un giusto compromesso.

Date un'occhiata alla documentazione per scipy.io.savemat e scipy.io.loadmat e anche questa pagina tutorial: scipy.io File IO Tutorial

7

ndarray.tofile() dovrebbe funzionare anche

esempioSe l'array è chiamato a:

a.tofile('yourfile.txt',sep=" ",format="%s") 

Non sei sicuro di come ottenere la formattazione a capo però.

Modifica (il commento di credito Kevin J. Nero here):

Since version 1.5.0, np.tofile() takes an optional parameter newline='\n' to allow multi-line output. https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.savetxt.html

+0

Ma c'è un modo per creare un array originale dal texfile? –

+0

@AhashanAlamSojib vedere https://stackoverflow.com/questions/3518778/how-to-read-csv-into-record-array-in-numpy – atomh33ls

0

Ho un modo per farlo utilizzando un'operazione semplice filename.write(). Funziona bene per me, ma ho a che fare con array aventi ~ 1500 elementi di dati.

Fondamentalmente ho solo cicli per scorrere il file e scriverlo alla destinazione di uscita riga per riga in un output in stile csv.

import numpy as np 

trial = np.genfromtxt("/extension/file.txt", dtype = str, delimiter = ",") 

with open("/extension/file.txt", "w") as f: 
    for x in xrange(len(trial[:,1])): 
     for y in range(num_of_columns): 
      if y < num_of_columns-2: 
       f.write(trial[x][y] + ",") 
      elif y == num_of_columns-1: 
       f.write(trial[x][y]) 
     f.write("\n") 

Le istruzioni if ​​e elif vengono utilizzate per aggiungere virgole tra gli elementi di dati. Per qualsiasi ragione, questi vengono eliminati quando si legge il file come un array nd. Il mio obiettivo era quello di generare il file come csv, quindi questo metodo aiuta a gestirlo.

Spero che questo aiuti!

Problemi correlati