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

또 다른 질문에서는 문제가있는 어레이를 제공 할 수 있다면 다른 사용자가 도움을 제공했습니다. 그러나 파일에 배열을 쓰는 것과 같은 기본 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)


답변

사람들이 파일을 읽을 수 있도록 만드는 데 관심이 있다고 생각하기 때문에 이것이 귀하의 요구 사항을 충족하는지 확실하지 않지만 이것이 주요 관심사가 아니라면 그저 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()


답변

사람이 읽을 수있는 출력이 필요하지 않은 경우 시도 할 수있는 또 다른 옵션은 배열을 .mat구조화 된 배열 인 MATLAB 파일 로 저장하는 것 입니다. 저는 MATLAB을 경멸합니다.하지만 .mat아주 적은 줄로 a 를 읽고 쓸 수 있다는 사실 이 편리합니다.

조 킹톤의 대답과는 달리, 이것의 장점은 당신이 없다는 것이다 데이터의 원래 모양을 알 필요가 없습니다 에서 .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 파일 IO 자습서


답변

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


답변

이를위한 특별한 라이브러리가 있습니다. (파이썬 용 래퍼 플러스)

도움이 되었기를 바랍니다


답변

세 개의 중첩 루프에서 배열을 탐색하고 해당 값을 파일에 기록하기 만하면됩니다. 읽기를 위해 동일한 정확한 루프 구성을 사용합니다. 배열을 다시 올바르게 채우기 위해 정확한 순서로 값을 얻을 수 있습니다.


답변

단순히 filename.write () 작업을 사용하여 수행하는 방법이 있습니다. 나를 위해 잘 작동하지만 ~ 1500 데이터 요소가있는 배열을 다루고 있습니다.

기본적으로 파일을 반복하고 csv 스타일 출력에서 ​​한 줄씩 출력 대상에 쓰는 for 루프가 있습니다.

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로 출력하는 것이기 때문에이 방법이이를 처리하는 데 도움이됩니다.

도움이 되었기를 바랍니다!