多次元配列をテキストファイルに書き込む方法


115

別の質問では、他のユーザーが、問題が発生したアレイを提供できるかどうかについていくつかの助けを提供しました。ただし、配列をファイルに書き込むなどの基本的なI / Oタスクでさえ失敗します。

ファイルに4x11x14のnumpy配列を書き込むために必要なループの種類を誰かが説明できますか?

この配列は4つの11 x 14配列で構成されているため、他のユーザーがファイルを読みやすくするために、適切な改行でフォーマットする必要があります。

編集:それで私はnumpy.savetxt関数を試しました。奇妙なことに、次のエラーが発生します。

TypeError: float argument required, not numpy.ndarray

これは、関数が多次元配列で機能しないためだと思いますか?私がそれらを1つのファイルに入れたい解決策はありますか?

回答:


197

numpy配列として簡単に読み戻すことができるようにディスクに書き込む場合は、を参照してくださいnumpy.save。ピクルス処理も問題なく動作しますが、大規模な配列の場合は効率が低下します(実際の配列ではそうではないため、どちらでも問題ありません)。

人間が読めるようにしたい場合は、を調べてくださいnumpy.savetxt

編集: つまり、savetxt2次元を超える配列のオプションとしてはそれほど優れていないようです...しかし、すべてを引き出すだけで完全な結論が得られます。

numpy.savetxt2次元を超えるndarrayのチョークに気づいたところです...テキストファイルで追加の次元を示すための本質的に定義された方法がないため、これはおそらく設計によるものです。

たとえば、これ(2D配列)は正常に動作します

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

TypeError: float argument required, not numpy.ndarray3D配列の場合、同じことは失敗します(かなり有益ではないエラー:) 。

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

1つの回避策は、3D(またはそれ以上)の配列を2Dスライスに分割することです。例えば

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)

ただし、私たちの目標は、はっきりと人間が読めるようにすると同時に、で簡単に読み返すことnumpy.loadtxtです。したがって、もう少し冗長にして、コメント化された行を使用してスライスを区別することができます。デフォルトでnumpy.loadtxtは、で始まる行#(またはcommentskwargで指定された文字)を無視します。(これは実際よりも冗長に見えます...)

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

これにより、

# 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

元の配列の形状がわかっていれば、それを読み取るのは非常に簡単です。できるだけですnumpy.loadtxt('test.txt').reshape((4,5,10))。例として(これを1行で行うことができますが、私は説明を明確にするために冗長にしています):

# 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
ここでのこの問題に対するはるかに簡単な解決策があります:yourStrArray = np.array([str(val)for val in yourMulDArray]、dtype = 'string'); np.savetxt( 'YourTextFile.txt'、yourStrArray、fmt = '%s')
グレッグクラミダ

@GregKramidaとアレイをどのように回復しますか?
astrojuanlu 2013

@ Juanlu001:numpy.loadtxt(...)は、np.string_に設定できるdtype引数も受け入れることを知っています。私はそれをまず第一に与えます。文字列から配列を解析するためのnumpy.fromstring(...)もあります。
グレッグクラミダ2013

画像配列を保存する必要がある場合はどうなりますか?画像サイズが512 x 512の場合、どのようにサイズを変更しますか?
Ambika Saxena 2017

31

これがあなたの要件を満たしているかどうかは定かではありません。ファイルを他の人が読めるようにすることに興味があると思いますが、それが主な関心事ではない場合は、pickleそれだけです。

保存するには:

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

それを読み返すには:

import pprint, pickle

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

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

pkl_file.close()

pprint辞書を印刷するために必要ないかもしれません。
zyy

11

人間が読める出力が必要ない場合は、配列を.mat構造化配列であるMATLAB ファイルとして保存することもできます。私はMATLABを嫌っていますが、読み取りと書き込みの両方.matをごくわずかの行で行えるというのは便利です。

Joe Kingtonの回答とは異なり、これの利点は、ファイル内のデータの元の形状を知る必要がないこと.matです。つまり、読み取り時に形状を変更する必要はありません。また、を使用するpickle場合とは異なり.mat、MATLABでファイルを読み取ることができます。そしておそらく他のいくつかのプログラム/言語も同様です。

次に例を示します。

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

配列の名前が.matファイルで指定されているキーを忘れた場合は、いつでも行うことができます。

print matdata.keys()

そしてもちろん、より多くのキーを使用して多くの配列を格納できます。

だからはい–目で読むことはできませんが、データの書き込みと読み取りに2行しかかからないので、これはかなりのトレードオフだと思います。

以下のためのドキュメントを見てみましょうscipy.io.savematscipy.io.loadmat もこのチュートリアルのページ:scipy.ioファイルIOチュートリアル


9

ndarray.tofile() うまくいくはず

たとえば、配列が呼び出された場合a

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

改行のフォーマットを取得する方法はわかりません。

編集(クレジットのKevin J. Blackのコメントはこちら):

バージョン1.5.0以降np.tofile()、オプションのパラメーター newline='\n'を使用して複数行の出力を可能にします。 https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.savetxt.html


しかし、texfileから元の配列を作成する方法はありますか?
Ahashan Alam Sojib

@AhashanAlamSojibは、stackoverflow.com
questions

tofileありませんnewline='\n'
NicoSchlömer、


1

3つのネストされたループで配列をトラバースし、それらの値をファイルに書き込むだけです。読むには、まったく同じループ構造を使用するだけです。配列を正しく埋めるために、正しい順序で値を取得します。


0

単純にfilename.write()操作を使用してそれを行う方法があります。それは私にとってはうまくいきますが、私は1500までのデータ要素を持つ配列を扱っています。

基本的には、forループでファイルを反復処理し、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")

ifおよびelifステートメントを使用して、データ要素間にコンマを追加します。なんらかの理由で、ファイルをnd配列として読み込むときに、これらは取り除かれます。私の目標は、ファイルをcsvとして出力することでした。そのため、このメソッドは、その処理に役立ちます。

お役に立てれば!


0

これらのケースにはピクルスが最適です。という名前のndarrayがあるとしますx_train。次のコマンドを使用して、ファイルにダンプし、元に戻すことができます。

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)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.