1. ホーム
  2. python

[解決済み] 多次元配列をテキストファイルに書き出すには?

2022-05-14 11:31:16

質問

別の質問で、他のユーザーは、私が困っている配列を提供することができれば、いくつかの助けを提供しました。しかし、私は、ファイルへの配列の書き込みのような基本的な I/O タスクでさえ失敗します。

4x11x14のnumpy配列をファイルに書き込むために、どのようなループが必要なのか、どなたか説明していただけますか?

この配列は4つの11 x 14の配列で構成されているので、私は他の人がファイルを読むのを容易にするために、素敵な改行でそれをフォーマットする必要があります。

編集 : というわけで、numpy.savetxtの関数を試してみました。不思議なことに、以下のようなエラーになります。

TypeError: float argument required, not numpy.ndarray

これは、この関数が多次元配列で動作しないためだと推測されます。私は1つのファイル内でそれらをしたいので、何か解決策がありますか?

どのように解決するのですか?

ディスクに書き込んで、numpyの配列として読み返しやすいようにしたい場合は、以下を調べます。 numpy.save . ピクルスも同様にうまくいきますが、大きな配列では効率が悪くなります(あなたの配列はそうではないので、どちらでも全く問題ありません)。

もし、人間が読めるようにしたいのであれば、次のものを見てください。 numpy.savetxt .

編集してください。 ということで、どうやら savetxt は、2次元の配列ではあまり良い選択肢ではないようです...。ただ、全てを完結に導き出すには

今気づいたのですが numpy.savetxt は 2 次元以上の ndarray を処理できないことに気づきました...。これはおそらく意図的なもので、テキスト ファイルに追加の次元を示すための固有の定義された方法はありません。

例えば、これ (2D 配列) は問題なく動作します。

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

同じことをしても失敗する一方で、(かなり不親切なエラーで。 TypeError: float argument required, not numpy.ndarray というエラーで)3D配列では失敗します。

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

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

x = np.arange(200).reshape((4,5,10))
with open('test.txt', 'w') as outfile:
    for slice_2d in x:
        np.savetxt(outfile, slice_2d)

しかし、私たちが目指しているのは、明らかに人間が読みやすいものでありながら、簡単に読み返せるような numpy.loadtxt . したがって、もう少し冗長にして、コメントアウトされた行を使用してスライスを区別することができます。デフォルトでは numpy.loadtxt で始まる行はすべて無視されます。 # (で始まる行は無視されます。 comments で指定された文字)。 (これは実際よりも冗長に見えますが...)

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)