wake-up-neo.com

Wie schreibe ich ein mehrdimensionales Array in eine Textdatei?

In einer anderen Frage boten andere Benutzer etwas Hilfe an, wenn ich das Array bereitstellen könnte, mit dem ich Probleme hatte. Ich scheitere jedoch sogar an einer grundlegenden E/A-Aufgabe, z. B. beim Schreiben eines Arrays in eine Datei.

Kann jemand erklären, welche Art von Schleife ich für ein 4x11x14-Numpy-Array in eine Datei schreiben müsste?

Dieses Array besteht aus vier 11 x 14-Arrays, daher sollte ich es mit einem Nice-Zeilenumbruch formatieren, um anderen das Lesen der Datei zu erleichtern.

Edit : Also habe ich die numpy.savetxt-Funktion ausprobiert. Seltsamerweise gibt es den folgenden Fehler:

TypeError: float argument required, not numpy.ndarray

Ich gehe davon aus, dass dies daran liegt, dass die Funktion mit mehrdimensionalen Arrays nicht funktioniert. Irgendwelche Lösungen, wie ich sie in einer Datei haben möchte?

90
Ivo Flipse

Wenn Sie es auf die Festplatte schreiben möchten, um es als Numpy-Array wieder einzulesen, schauen Sie in numpy.save . Das Beizen funktioniert ebenfalls gut, ist jedoch bei großen Arrays weniger effizient (was bei Ihnen nicht der Fall ist, und ist auch vollkommen in Ordnung).

Wenn Sie möchten, dass es für Menschen lesbar ist, schauen Sie in numpy.savetxt .

Edit: Es sieht also so aus, als wäre savetxt für Arrays mit> 2 Dimensionen nicht ganz so gut geeignet ... Aber um alles auf den Punkt zu bringen:

Ich habe gerade erkannt, dass numpy.savetxt auf ndarrays mit mehr als 2 Dimensionen erstickt ... Dies ist wahrscheinlich beabsichtigt, da es keine inhärent definierte Möglichkeit gibt, zusätzliche Dimensionen in einer Textdatei anzugeben.

Z.B. Dieses (ein 2D-Array) funktioniert gut

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

Dasselbe würde für ein 3D-Array fehlschlagen (mit einem nicht informativen Fehler: TypeError: float argument required, not numpy.ndarray):

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

Eine Problemumgehung besteht darin, das 3D-Array (oder ein höheres Array) in 2D-Schnitte aufzuteilen. Z.B.

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)

Unser Ziel ist es jedoch, klar lesbar zu sein und dennoch mit numpy.loadtxt leicht lesbar zu sein. Daher können wir etwas ausführlicher sein und die Slices anhand von auskommentierten Zeilen unterscheiden. Standardmäßig ignoriert numpy.loadtxt alle Zeilen, die mit # beginnen (oder welches Zeichen von comments kwarg angegeben wird). (Das sieht viel ausführlicher aus, als es tatsächlich ist ...)

import numpy as np

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

# Write the array to disk
with open('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')

Dies ergibt:

# 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

Es ist sehr leicht, es wieder einzulesen, solange wir die Form des ursprünglichen Arrays kennen. Wir können einfach numpy.loadtxt('test.txt').reshape((4,5,10)) machen. Als Beispiel (Sie können dies in einer Zeile tun, ich bin nur wortreich, um Dinge zu klären):

# 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)
170
Joe Kington

Ich bin nicht sicher, ob dies Ihren Anforderungen entspricht, da ich glaube, dass Sie daran interessiert sind, die Datei für Menschen lesbar zu machen, aber wenn dies nicht ein Hauptanliegen ist, nur pickle it.

Um es zu speichern:

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(my_data, output)
output.close()

Um es zurückzulesen:

import pprint, pickle

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

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

pkl_file.close()
26
Dominic Rodger

Wenn Sie keine vom Menschen lesbare Ausgabe benötigen, können Sie das Array auch als MATLAB .mat-Datei speichern, bei der es sich um ein strukturiertes Array handelt. Ich hasse MATLAB, aber die Tatsache, dass ich einen .mat in sehr wenigen Zeilen sowohl lesen als auch schreiben kann, ist praktisch. 

Im Gegensatz zur Antwort von Joe Kington besteht der Vorteil darin, dass Sie Sie müssen die ursprüngliche Form der Daten nicht kennen in der .mat-Datei, dh, Sie müssen sich beim Einlesen nicht umformen. Und anders als bei pickle Eine .mat-Datei kann von MATLAB gelesen werden, möglicherweise auch einige andere Programme/Sprachen. 

Hier ist ein Beispiel:

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'])

Wenn Sie den Schlüssel vergessen, den das Array in der Datei .mat benannt hat, können Sie immer Folgendes tun:

print matdata.keys()

Natürlich können Sie viele Arrays mit vielen weiteren Schlüsseln speichern.

Also ja - es ist mit Ihren Augen nicht lesbar, aber es dauert nur 2 Zeilen, um die Daten zu schreiben und zu lesen, was meiner Meinung nach ein fairer Kompromiss ist.

Sehen Sie sich die Dokumentation für scipy.io.savemat Und scipy.io.loadmat Sowie diese Tutorial-Seite an: scipy.io File IO Tutorial

10
aseagram

ndarray.tofile() sollte auch funktionieren

z.B. wenn Ihr Array a heißt:

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

Sie sind sich jedoch nicht sicher, wie Sie die Formatierung der Zeilen erreichen können.

Edit (Anrede von Kevin J. Black hier ):

Seit Version 1.5.0 übernimmt np.tofile() einen optionalen Parameter newline='\n', um eine mehrzeilige Ausgabe zu ermöglichen . https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.savetxt.html

7
atomh33ls

Dafür gibt es spezielle Bibliotheken. (Plus Wrapper für Python)

hoffe das hilft

3
Ronny Brendel

Sie können das Array einfach in drei verschachtelten Schleifen durchlaufen und deren Werte in Ihre Datei schreiben. Zum Lesen verwenden Sie einfach dieselbe exakte Schleifenkonstruktion. Sie erhalten die Werte genau in der richtigen Reihenfolge, um Ihre Arrays wieder korrekt zu füllen.

1
jwueller

Pickle ist am besten für diese Fälle. Angenommen, Sie haben ein ndarray namens x_train. Sie können es in eine Datei sichern und mit dem folgenden Befehl wiederherstellen:

import pickle

###Load into file
with open("myfile.pkl","wb") as f:
    pickle.dump(x_train,f)

###Extract from file
with open("myfile.pkl","rb") as f:
    x_temp = pickle.load(f)
0
Kenpachi Zaraki

Ich habe eine Möglichkeit, dies mit einer einfachen dateiname.write () - Operation zu tun. Es funktioniert gut für mich, aber ich habe es mit Arrays zu tun, die ~ 1500 Datenelemente haben. 

Ich habe im Grunde nur für Schleifen, um die Datei zu durchlaufen und sie zeilenweise in einer Ausgabe im CSV-Stil an das Ausgabeziel zu schreiben. 

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")

Die if- und Elif-Anweisung werden zum Hinzufügen von Kommas zwischen den Datenelementen verwendet. Aus welchem ​​Grund auch immer, werden diese beim Lesen der Datei als ein Array gelöscht. Mein Ziel war es, die Datei als csv auszugeben, daher hilft diese Methode, damit umzugehen.

Hoffe das hilft!

0
BennyD