Programming

다차원 배열을 텍스트 파일에 쓰는 방법은 무엇입니까?

procodes 2020. 8. 18. 19:25
반응형

다차원 배열을 텍스트 파일에 쓰는 방법은 무엇입니까?


또 다른 질문에서는 문제가 발생한 어레이를 제공 할 수 있으면 다른 사용자가 도움을 제공했습니다. 그러나 파일에 배열을 쓰는 것과 같은 기본적인 I / O 작업에서도 실패합니다.

누구든지 4x11x14 numpy 배열을 파일에 작성하는 데 필요한 루프의 종류를 설명 할 수 있습니까?

이 배열은 4 개의 11 x 14 배열로 구성되어 있으므로 다른 사람이 파일을 더 쉽게 읽을 수 있도록 멋진 줄 바꿈으로 형식을 지정해야합니다.

편집 : 그래서 numpy.savetxt 기능을 시도했습니다. 이상하게도 다음과 같은 오류가 발생합니다.

TypeError: float argument required, not numpy.ndarray

함수가 다차원 배열에서 작동하지 않기 때문이라고 생각합니까? 하나의 파일에서 원하는 솔루션이 있습니까?


numpy 배열로 쉽게 다시 읽을 수 있도록 디스크에 쓰려면 numpy.save. 산세도 잘 작동하지만 큰 배열의 경우 효율성이 떨어집니다 (당신의 것이 아니므로 둘 다 완벽하게 좋습니다).

사람이 읽을 수 있도록하려면 numpy.savetxt.

편집 : 그래서, 그것은 savetxt> 2 차원을 가진 배열에 대한 옵션만큼 좋지 않은 것 같습니다 ...하지만 모든 것을 그에 맞게 그리는 것은 완전한 결론입니다.

나는 단지 numpy.savetxt2 차원 이상의 ndarrays에서 질식 한다는 것을 깨달았습니다 . 이것은 텍스트 파일에 추가 차원을 표시하는 본질적으로 정의 된 방법이 없기 때문에 아마도 의도적으로 설계된 것입니다.

예 : 이것은 (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)

한 가지 해결 방법은 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)). 예를 들어 (한 줄로이 작업을 수행 할 수 있습니다. 설명하기 위해 자세히 설명하겠습니다.)

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

I am not certain if this meets your requirements, given I think you are interested in making the file readable by people, but if that's not a primary concern, just pickle it.

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

To read it back:

import pprint, pickle

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

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

pkl_file.close()

If you don't need a human-readable output, another option you could try is to save the array as a MATLAB .mat file, which is a structured array. I despise MATLAB, but the fact that I can both read and write a .mat in very few lines is convenient.

Unlike Joe Kington's answer, the benefit of this is that you don't need to know the original shape of the data in the .mat file, i.e. no need to reshape upon reading in. And, unlike using pickle, a .mat file can be read by MATLAB, and probably some other programs/languages as well.

Here is an example:

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

If you forget the key that the array is named in the .mat file, you can always do:

print matdata.keys()

And of course you can store many arrays using many more keys.

So yes – it won't be readable with your eyes, but only takes 2 lines to write and read the data, which I think is a fair trade-off.

Take a look at the docs for scipy.io.savemat and scipy.io.loadmat and also this tutorial page: scipy.io File IO Tutorial


ndarray.tofile() should also work

e.g. if your array is called a:

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

Not sure how to get newline formatting though.

Edit (credit Kevin J. Black's comment 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


There exist special libraries to do just that. (Plus wrappers for python)

hope this helps


You can simply traverse the array in three nested loops and write their values to your file. For reading, you simply use the same exact loop construction. You will get the values in exactly the right order to fill your arrays correctly again.


I have a way to do it using a simply filename.write() operation. It works fine for me, but I'm dealing with arrays having ~1500 data elements.

I basically just have for loops to iterate through the file and write it to the output destination line-by-line in a csv style output.

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

The if and elif statement are used to add commas between the data elements. For whatever reason, these get stripped out when reading the file in as an nd array. My goal was to output the file as a csv, so this method helps to handle that.

Hope this helps!


Pickle is best for these cases. Suppose you have a ndarray named x_train. You can dump it into a file and revert it back using the following command:

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)

참고URL : https://stackoverflow.com/questions/3685265/how-to-write-a-multidimensional-array-to-a-text-file

반응형