python - recorrer - ¿Cómo escribir una matriz multidimensional en un archivo de texto?
que es numpy (7)
Existen bibliotecas especiales para hacer justamente eso. (Más envoltorios para pitón)
- netCDF4: http://www.unidata.ucar.edu/software/netcdf/
Interfaz de netCDF4 Python: http://www.unidata.ucar.edu/software/netcdf/software.html#Python
espero que esto ayude
En otra pregunta, otros usuarios me ofrecieron ayuda si podía suministrar la matriz con la que estaba teniendo problemas. Sin embargo, incluso fallo en una tarea de E / S básica, como escribir una matriz en un archivo.
¿Alguien puede explicar qué tipo de bucle necesitaría para escribir una matriz nux 4x11x14?
Esta matriz consta de cuatro matrices de 11 x 14, por lo que debería formatearla con una nueva línea agradable, para facilitar la lectura del archivo en otras.
Editar : Así que probé la función numpy.savetxt. Extrañamente, da el siguiente error:
TypeError: float argument required, not numpy.ndarray
Supongo que esto se debe a que la función no funciona con matrices multidimensionales. ¿Alguna solución como me gustaría dentro de un archivo?
No estoy seguro de si esto satisface sus requisitos, dado que creo que está interesado en hacer que el archivo sea legible por las personas, pero si eso no es una preocupación principal, solo pickle
.
Para guardarlo:
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()
Para leerlo de nuevo:
import pprint, pickle
pkl_file = open(''data.pkl'', ''rb'')
data1 = pickle.load(pkl_file)
pprint.pprint(data1)
pkl_file.close()
Si desea escribirlo en el disco para que sea fácil volver a leerlo como una matriz numpy, mire en numpy.save
. El decapado también funcionará bien, pero es menos eficiente para arreglos grandes (que el tuyo no lo es, así que tampoco está bien).
Si quieres que sea legible por humanos, mira en numpy.savetxt
.
Editar: Entonces, parece que savetxt
no es una opción tan buena para arreglos con> 2 dimensiones ... Pero solo para sacar todo a su conclusión:
Me acabo de dar cuenta de que numpy.savetxt
en las ndarrays con más de 2 dimensiones ... Probablemente esto sea por diseño, ya que no hay una forma inherentemente definida de indicar dimensiones adicionales en un archivo de texto.
Ej. Esto (una matriz 2D) funciona bien
import numpy as np
x = np.arange(20).reshape((4,5))
np.savetxt(''test.txt'', x)
Mientras que lo mismo fallaría (con un error poco informativo: se TypeError: float argument required, not numpy.ndarray
) para una matriz 3D:
import numpy as np
x = np.arange(200).reshape((4,5,10))
np.savetxt(''test.txt'', x)
Una solución es simplemente dividir la matriz 3D (o superior) en segmentos 2D. P.ej
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)
Sin embargo, nuestro objetivo es ser claramente legible, al mismo tiempo que se lee fácilmente con numpy.loadtxt
. Por lo tanto, podemos ser un poco más detallados y diferenciar los sectores utilizando líneas comentadas. De forma predeterminada, numpy.loadtxt
ignorará cualquier línea que comience con #
(o cualquier carácter especificado por los comments
kwarg). (Esto se ve más prolijo de lo que realmente es ...)
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'')
Esto 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
Leerlo de nuevo es muy fácil, siempre que sepamos la forma de la matriz original. Podemos simplemente hacer numpy.loadtxt(''test.txt'').reshape((4,5,10))
. Como ejemplo (Puedes hacer esto en una línea, solo estoy siendo prolijo para aclarar cosas):
# 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)
Si no necesita una salida legible para los humanos, otra opción que puede probar es guardar la matriz como un archivo .mat
MATLAB, que es una matriz estructurada. Desprecio a MATLAB, pero el hecho de que pueda leer y escribir un .mat
en muy pocas líneas es conveniente.
A diferencia de la respuesta de Joe Kington, el beneficio de esto es que no necesita conocer la forma original de los datos en el archivo .mat
, es decir, no necesita una .mat
al leer. Y, a diferencia del uso de pickle
, un archivo .mat
puede ser leído por MATLAB, y probablemente algunos otros programas / idiomas también.
Aquí hay un ejemplo:
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''])
Si olvida la clave que la matriz se nombra en el archivo .mat
, siempre puede hacer:
print matdata.keys()
Y, por supuesto, puede almacenar muchas matrices utilizando muchas más claves.
Entonces sí, no será legible con sus ojos, solo toma 2 líneas para escribir y leer los datos, lo cual creo que es una compensación justa.
Eche un vistazo a los documentos para scipy.io.savemat y scipy.io.loadmat y también esta página de tutorial: scipy.io File IO Tutorial
Simplemente puede atravesar la matriz en tres bucles anidados y escribir sus valores en su archivo. Para leer, simplemente usa la misma construcción exacta de bucle. Obtendrá los valores exactamente en el orden correcto para llenar sus matrices correctamente de nuevo.
Tengo una forma de hacerlo usando una operación simple filename.write (). Funciona bien para mí, pero estoy tratando con matrices que tienen ~ 1500 elementos de datos.
Básicamente, tengo que hacer que los bucles iteren a través del archivo y lo escriban en el destino de salida línea por línea en una salida de estilo 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")
La instrucción if y elif se usan para agregar comas entre los elementos de datos. Por alguna razón, estos se eliminan cuando se lee el archivo como una matriz nd. Mi objetivo era generar el archivo como un csv, por lo que este método ayuda a manejar eso.
¡Espero que esto ayude!
ndarray.tofile()
también debería funcionar
por ejemplo, si su matriz se llama a
:
a.tofile(''yourfile.txt'',sep=" ",format="%s")
Sin embargo, no estoy seguro de cómo obtener el formato de nueva línea.
Editar (crédito de comentario de Kevin J. Black here ):
Desde la versión 1.5.0,
np.tofile()
toma un parámetro opcionalnewline=''/n''
para permitir la salida de varias líneas. https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.savetxt.html