Làm thế nào để ghi một mảng nhiều chiều vào tệp văn bản?


115

Trong một câu hỏi khác, những người dùng khác đã đề nghị một số trợ giúp nếu tôi có thể cung cấp mảng mà tôi đang gặp sự cố. Tuy nhiên, tôi thậm chí còn thất bại ở một tác vụ I / O cơ bản, chẳng hạn như ghi một mảng vào tệp.

Bất cứ ai có thể giải thích loại vòng lặp tôi sẽ cần để viết một mảng 4x11x14 numpy vào tệp?

Mảng này bao gồm bốn mảng 11 x 14, vì vậy tôi nên định dạng nó bằng một dòng mới đẹp, để làm cho việc đọc tệp đối với những người khác dễ dàng hơn.

Chỉnh sửa : Vì vậy, tôi đã thử chức năng numpy.savetxt. Thật kỳ lạ, nó đưa ra lỗi sau:

TypeError: float argument required, not numpy.ndarray

Tôi giả sử rằng điều này là do hàm không hoạt động với mảng nhiều chiều? Bất kỳ giải pháp như tôi muốn chúng trong một tệp?

Câu trả lời:


197

Nếu bạn muốn ghi nó vào đĩa để dễ dàng đọc lại dưới dạng một mảng phức tạp, hãy xem xét numpy.save. Nhặt nó cũng sẽ hoạt động tốt, nhưng nó kém hiệu quả hơn đối với các mảng lớn (cái của bạn không có, vì vậy một trong hai cũng hoàn toàn ổn).

Nếu bạn muốn con người có thể đọc được, hãy xem xét numpy.savetxt.

Chỉnh sửa: Vì vậy, có vẻ như savetxtkhông phải là một lựa chọn tuyệt vời cho các mảng có> 2 kích thước ... Nhưng chỉ để rút ra mọi thứ cho nó kết luận đầy đủ:

Tôi chỉ nhận ra rằng numpy.savetxtcuộn cảm trên ndarrays có nhiều hơn 2 kích thước ... Điều này có thể là do thiết kế, vì không có cách xác định nào để chỉ ra các kích thước bổ sung trong tệp văn bản.

Vd: Cái này (mảng 2D) hoạt động tốt

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

Mặc dù điều tương tự sẽ không thành công (với một lỗi khá không thông tin TypeError: float argument required, not numpy.ndarray:) đối với mảng 3D:

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

Một cách giải quyết là chỉ chia mảng 3D (hoặc lớn hơn) thành các lát 2D. Ví dụ

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)

Tuy nhiên, mục tiêu của chúng tôi là con người có thể đọc được một cách rõ ràng, trong khi vẫn có thể dễ dàng đọc lại với numpy.loadtxt. Do đó, chúng ta có thể dài dòng hơn một chút và phân biệt các lát cắt bằng cách sử dụng các dòng đã nhận xét. Theo mặc định, numpy.loadtxtsẽ bỏ qua bất kỳ dòng nào bắt đầu bằng #(hoặc bất kỳ ký tự nào được chỉ định bởi commentskwarg). (Điều này trông dài dòng hơn so với thực tế ...)

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

Điều này mang lại:

# 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

Đọc lại nó rất dễ dàng, miễn là chúng ta biết hình dạng của mảng ban đầu. Chúng tôi chỉ có thể làm numpy.loadtxt('test.txt').reshape((4,5,10)). Ví dụ (Bạn có thể làm điều này trong một dòng, tôi chỉ nói dài dòng để làm rõ mọi thứ):

# 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
Có một giải pháp dễ dàng hơn nhiều cho vấn đề này bây giờ: yourStrArray = np.array ([str (val) for val in yourMulDArray], dtype = 'string'); np.savetxt ('YourTextFile.txt', yourStrArray, fmt = '% s')
Greg Kramida 13/12/12

@GregKramida và làm cách nào để bạn khôi phục mảng?
astrojuanlu

@ Juanlu001: Tôi biết rằng numpy.loadtxt (...) cũng chấp nhận đối số kiểu dtype, có thể được đặt thành np.string_. Tôi sẽ cho rằng một shot, đầu tiên và quan trọng nhất. Ngoài ra còn có một numpy.fromstring (...) để phân tích cú pháp mảng từ chuỗi.
Greg Kramida

Này nếu tôi cần lưu trữ một mảng hình ảnh thì sao? Làm thế nào chúng tôi sẽ thay đổi kích thước đó nếu kích thước hình ảnh được cho là, 512 x 512?
Ambika Saxena,

31

Tôi không chắc liệu điều này có đáp ứng được yêu cầu của bạn hay không, vì tôi nghĩ rằng bạn quan tâm đến việc làm cho tệp có thể đọc được bởi mọi người, nhưng nếu đó không phải là mối quan tâm chính, thì chỉ cần picklenó.

Để lưu nó:

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

Để đọc lại:

import pprint, pickle

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

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

pkl_file.close()

Bạn có thể không cần pprintđể in từ điển.
zyy

11

Nếu bạn không cần đầu ra mà con người có thể đọc được, một tùy chọn khác mà bạn có thể thử là lưu mảng dưới dạng .mattệp MATLAB , là một mảng có cấu trúc. Tôi coi thường MATLAB, nhưng thực tế là tôi có thể vừa đọc vừa viết một .matvài dòng rất tiện lợi.

Không giống như câu trả lời của Joe Kington, lợi ích của việc này là bạn không cần biết hình dạng ban đầu của dữ liệu trong .mattệp, tức là không cần phải định hình lại khi đọc vào. Và, không giống như cách sử dụng pickle, .matMATLAB có thể đọc tệp, và có thể là một số chương trình / ngôn ngữ khác.

Đây là một ví dụ:

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

Nếu bạn quên khóa mà mảng được đặt tên trong .mattệp, bạn luôn có thể thực hiện:

print matdata.keys()

Và tất nhiên bạn có thể lưu trữ nhiều mảng bằng cách sử dụng nhiều khóa hơn.

Vì vậy, có - nó sẽ không thể đọc được bằng mắt của bạn, nhưng chỉ mất 2 dòng để viết và đọc dữ liệu, tôi nghĩ đó là một sự đánh đổi công bằng.

Hãy xem các tài liệu dành cho scipy.io.savematscipy.io.loadmat và cả trang hướng dẫn này: scipy.io File IO Tutorial


9

ndarray.tofile() cũng nên làm việc

ví dụ: nếu mảng của bạn được gọi là a:

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

Tuy nhiên, không chắc chắn về cách lấy định dạng dòng mới.

Chỉnh sửa (ghi nhận bình luận của Kevin J. Black ở đây ):

Kể từ phiên bản 1.5.0, np.tofile()có một tham số tùy chọn newline='\n'để cho phép đầu ra nhiều dòng. https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.savetxt.html


Nhưng có cách nào để tạo mảng ban đầu từ texfile không?
Ahashan Alam Sojib


tofilekhông có newline='\n'.
Nico Schlömer


1

Bạn có thể chỉ cần duyệt qua mảng trong ba vòng lặp lồng nhau và ghi giá trị của chúng vào tệp của bạn. Để đọc, bạn chỉ cần sử dụng cùng một cấu trúc vòng lặp chính xác. Bạn sẽ nhận được các giá trị theo thứ tự chính xác để điền lại các mảng của mình một cách chính xác.


0

Tôi có một cách để làm điều đó bằng cách sử dụng một thao tác đơn giản là filename.write (). Nó hoạt động tốt đối với tôi, nhưng tôi đang xử lý các mảng có ~ 1500 phần tử dữ liệu.

Về cơ bản, tôi chỉ có vòng lặp for để lặp qua tệp và ghi nó vào đầu ra đích đầu ra từng dòng một trong đầu ra kiểu 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")

Câu lệnh if và elif được sử dụng để thêm dấu phẩy giữa các phần tử dữ liệu. Vì bất kỳ lý do gì, chúng sẽ bị loại bỏ khi đọc tệp dưới dạng mảng thứ n. Mục tiêu của tôi là xuất tệp dưới dạng csv, vì vậy phương pháp này giúp xử lý điều đó.

Hi vọng điêu nay co ich!


0

Đồ chua là tốt nhất cho những trường hợp này. Giả sử bạn có một ndarray được đặt tên x_train. Bạn có thể kết xuất nó vào một tệp và hoàn nguyên nó trở lại bằng lệnh sau:

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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.