web-dev-qa-db-ja.com

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

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

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

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

編集:だから、numpy.savetxt関数を試しました。奇妙なことに、次のエラーが発生します。

TypeError: float argument required, not numpy.ndarray

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

96
Ivo Flipse

Numpy配列として読みやすいようにディスクに書き込みたい場合は、 numpy.save を調べてください。酸洗もうまくいきますが、大きな配列では効率が悪くなります(あなたの配列はそうではないので、どちらも完全にうまくいきます)。

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

Edit:したがって、savetxtは2次元を超える配列にはあまり適したオプションではないように思われますが...完全な結論です:

numpy.savetxtが2次元以上のndarrayでチョークすることに気付きました...テキストファイルに追加の次元を示す固有の定義された方法がないため、これはおそらく設計によるものです。

例えば。これ(2D配列)は正常に動作します

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

3D配列の場合も同じことが失敗します(むしろ情報価値のないエラー:TypeError: float argument required, not numpy.ndarray):

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#(またはcomments kwargで指定された文字)で始まる行を無視します。 (これは実際よりも冗長に見えます...)

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)
176
Joe Kington

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

保存するには:

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()
28
Dominic Rodger

人間が読める出力を必要としない場合は、配列をMATLAB .matファイルとして保存することもできます。これは構造化配列です。私はMATLABを軽deしていますが、.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.savemat および scipy.io.loadmat のドキュメントと、このチュートリアルページをご覧ください: scipy.io File IOチュートリアル

10
aseagram

ndarray.tofile() も動作するはずです

例えば配列がaと呼ばれる場合:

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

ただし、改行の書式設定を取得する方法がわからない。

Edit(Kevin J. Blackのコメントをクレジット here ):

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

7
atomh33ls

それを行う特別なライブラリが存在します。 (pythonのラッパー)

お役に立てれば

3
Ronny Brendel

単純に3つのネストされたループで配列を走査し、それらの値をファイルに書き込むことができます。読み取りには、同じ正確なループ構造を使用するだけです。配列を再び正しく埋めるために、正しい順序で値を取得します。

1
jwueller

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

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

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

基本的には、forループを使用してファイルを反復処理し、csvスタイルの出力で1行ずつ出力先に書き込みます。

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
BennyD