2010-09-10 4 views
79

Dans une autre question, d'autres utilisateurs ont offert de l'aide si je pouvais fournir le tableau avec lequel j'avais des problèmes. Cependant, j'échoue même à une tâche d'E/S de base, telle que l'écriture d'un tableau dans un fichier. Est-ce que quelqu'un peut expliquer le type de boucle dont j'aurais besoin pour écrire un tableau 4x11x14 numpy dans un fichier?Comment écrire un tableau multidimensionnel dans un fichier texte?

Ce tableau est constitué de quatre tableaux 11 x 14, donc je devrais le formater avec un nouveau saut de ligne, pour faciliter la lecture du fichier sur d'autres.

Modifier: J'ai donc essayé la fonction numpy.savetxt. Étrangement, il donne l'erreur suivante:

TypeError: float argument required, not numpy.ndarray 

Je suppose que cela est parce que la fonction ne fonctionne pas avec des tableaux multidimensionnels? Des solutions comme je les voudrais dans un fichier?

+0

Désolé, relisez votre question après avoir posté ma réponse, et soupçonnez qu'elle ne répond pas à vos besoins - si ce n'est pas le cas, envoyez-moi un message ping et je posterai une alternative. (Bon de vous voir dans cette partie de l'ex-quadrilogie btw!) –

+0

En fait - ressemble à la réponse de Joe Kington devrait fonctionner pour vous. –

Répondre

149

Si vous voulez l'écrire sur le disque pour qu'il soit facile à lire en tant que tableau numpy, regardez numpy.save. Le décapage fonctionnera bien aussi, mais il est moins efficace pour les grandes piles (ce qui n'est pas le cas, donc tout va bien).

Si vous voulez qu'il soit lisible par l'homme, regardez numpy.savetxt.

Edit: Ainsi, il semble que savetxt est pas tout à fait aussi grande une option pour les tableaux avec> 2 dimensions ... Mais juste pour tirer tout sur à sa conclusion complète:

Je viens de réaliser que numpy.savetxt étranglements sur ndarrays avec plus de 2 dimensions ... Ceci est probablement de par sa conception, car il n'y a pas de manière intrinsèquement définie d'indiquer des dimensions supplémentaires dans un fichier texte.

E.g. Ce (un tableau 2D) fonctionne très bien

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

Alors que la même chose échouerait (avec une erreur assez peu significatives: TypeError: float argument required, not numpy.ndarray) pour un tableau 3D:

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

Une solution de contournement est juste pour briser la 3D (ou plus grand) tableau en tranches 2D. Par exemple.

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) 

Cependant, notre objectif est d'être lisible, tout en étant facilement lu encore clairement humaine retour avec numpy.loadtxt. Par conséquent, nous pouvons être un peu plus verbeux, et différencier les tranches en utilisant des lignes commentées. Par défaut, numpy.loadtxt ignorera toutes les lignes commençant par # (ou le caractère spécifié par le comments kwarg). (Cela semble plus bavard qu'il est en fait ...)

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

Cela donne:

# 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 

relisant en est très facile, aussi longtemps que nous connaissons la forme du tableau d'origine. Nous pouvons simplement faire numpy.loadtxt('test.txt').reshape((4,5,10)). À titre d'exemple (Vous pouvez le faire en une ligne, je vais être bavard pour clarifier les choses):

# 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 de moi, voir aussi 'numpy.loadtxt' (http://docs.scipy.org/doc/numpy/reference/generated/numpy.loadtxt. html) –

+0

Bien l'avoir lisible comme texte est très utile aussi, si vous pouvez formater votre réponse avec un petit exemple de code, je vais accepter votre réponse :-) –

+0

Je dois attraper le bus, mais je vais ajouter un exemple de code dès que je rentre ... Merci! –

22

Je ne suis pas certain si cela répond à vos besoins, étant donné que je pense que vous êtes intéressé à rendre le fichier lisible par les gens, mais si ce n'est pas une préoccupation majeure, juste pickle.

Pour enregistrer:

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

Pour relis:

import pprint, pickle 

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

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

pkl_file.close() 
+0

@ badbod99 - parce que la réponse de Joe Kington est meilleure que la mienne :) –

1

Vous pouvez simplement parcourir le tableau en trois boucles imbriquées et écrire leurs valeurs dans votre fichier. Pour la lecture, vous utilisez simplement la même construction en boucle exacte. Vous obtiendrez les valeurs exactement dans le bon ordre pour remplir vos tableaux correctement à nouveau.

7

Si vous n » t besoin d'une sortie lisible par l'homme, une autre option que vous pourriez t ry est de sauvegarder le tableau sous la forme d'un fichier MATLAB .mat, qui est un tableau structuré. Je déteste MATLAB, mais le fait que je puisse à la fois lire et écrire un .mat en très peu de lignes est pratique.

Contrairement à la réponse de Joe Kington, l'avantage est que vous ne pas besoin de connaître la forme originale des données dans le fichier .mat, soit pas nécessaire de remodeler la lecture. Et, contrairement à l'utilisation pickle, un fichier .mat peut être lu par MATLAB, et probablement d'autres programmes/langues aussi.

Voici un exemple:

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 vous oubliez la clé que le tableau est nommé dans le fichier .mat, vous pouvez toujours faire:

print matdata.keys() 

Et bien sûr, vous pouvez stocker beaucoup tableaux utilisant beaucoup plus de clés. Donc oui - il ne sera pas lisible avec vos yeux, mais ne prend que 2 lignes pour écrire et lire les données, ce qui me semble être un compromis équitable.

Jetez un oeil à la documentation pour scipy.io.savemat et scipy.io.loadmat et aussi cette page tutoriel: scipy.io File IO Tutorial

7

ndarray.tofile() devrait également travailler

par exemplesi votre tableau est appelé a:

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

Je ne sais pas comment obtenir la mise en forme si saut de ligne.

Modifier (crédit Kevin J. Black 'commentaire 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

Mais existe-t-il un moyen de créer un tableau original à partir du fichier tex? –

+0

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

0

J'ai une façon de le faire en utilisant simplement une opération filename.write(). Cela fonctionne bien pour moi, mais je fais face à des tableaux ayant ~ 1500 éléments de données. En gros, je n'ai que des boucles pour parcourir le fichier et l'écrire ligne par ligne dans une sortie de style 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") 

Les instructions if et elif sont utilisées pour ajouter des virgules entre les éléments de données. Pour une raison quelconque, ils sont supprimés lors de la lecture du fichier sous forme de tableau nd. Mon but était de produire le fichier en tant que csv, donc cette méthode aide à gérer cela.

Espérons que cela aide!

Questions connexes