2010-09-10 5 views
79

В другом вопросе другие пользователи предложили некоторую помощь, если я могу предоставить массив, с которым у меня были проблемы. Тем не менее, я даже не выполняю основную задачу ввода-вывода, например, запись массива в файл.Как написать многомерный массив в текстовый файл?

Может ли кто-нибудь объяснить, какой цикл мне понадобится для записи массива numx 4x11x14 в файл?

Этот массив состоит из четырех массивов 11 x 14, поэтому я должен отформатировать его с помощью новой строки, чтобы упростить чтение файла на других.

Редактировать: Итак, я пробовал функцию numpy.savetxt. Как ни странно, это дает следующее сообщение об ошибке:

TypeError: float argument required, not numpy.ndarray 

Я предполагаю, что это происходит потому, что функция не работает с многомерными массивами? Любые решения, как я хотел бы их в одном файле?

+0

Извините, перечитайте свой вопрос после отправки моего ответа и предположите, что он не отвечает вашим потребностям - если это не так, напишите мне, и я отправлю альтернативу. (Хорошо видеть вас в этой части экс-квадрилогии btw!) –

+0

На самом деле - похоже, ответ Джо Кингтона должен работать на вас. –

ответ

149

Если вы хотите записать его на диск, чтобы его можно было легко считывать в виде массива numpy, посмотрите на numpy.save. Распиловка также будет работать отлично, но она менее эффективна для больших массивов (чего у вас нет, так и отлично).

Если вы хотите, чтобы это был человек, читаемый, просмотрите numpy.savetxt.

Edit: Так, похоже, savetxt не столь большой вариант для массивов с> 2-х измерениях ... Но просто сделать все, чтобы это полный вывод:

Я просто понял, что numpy.savetxt дроссели на ndarrays с более чем 2-мя измерениями ... Это, по-видимому, по дизайну, так как нет никакого определенного способа указать дополнительные размеры в текстовом файле.

E.g. Это (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 (или больше) в двумерные срезы. Например.

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 file('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) 
+2

+1 от меня, см. Также 'numpy.loadtxt' (http://docs.scipy.org/doc/numpy/reference/generated/numpy.loadtxt. html) –

+0

Хорошо, что его можно читать, так как текст очень полезен, если вы можете отформатировать свой ответ с помощью небольшого примера кода, я приму свой ответ :-) –

+0

Мне нужно поймать автобус, но я добавлю пример кода, как только я получу ... Спасибо! –

22

Я не уверен, что это соответствует вашим требованиям, учитывая, что я думаю, что вы заинтересованы в том, чтобы сделать файл доступным для чтения людьми, но если это не главное, просто 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(data1, output) 
output.close() 

Чтобы прочитать его обратно:

import pprint, pickle 

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

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

pkl_file.close() 
+0

@ badbod99 - потому что ответ Джо Кингтона лучше моего :) –

1

Вы можете просто пройти через массив в трех вложенных циклов и записать их значения в файл. Для чтения вы просто используете ту же самую точную конструкцию цикла. Вы получите значения точно в правильном порядке, чтобы снова заполнить свои массивы.

7

Если вы не» t требуется удобочитаемый вывод, другой вариант, который вы могли бы ry должен сохранить массив как файл MATLAB .mat, который является структурированным массивом. Я презираю MATLAB, но факт, что я могу читать и писать .mat в очень немногих строках, удобен.

В отличии от ответа Джо 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 Tutorial

7

ndarray.tofile() должны также работать

напримересли массив называется a:

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

Не знаю, как получить перевод строки форматирования, хотя.

Редактировать (комментарий кредитной Kevin J. Блэка 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

+0

Но есть ли способ создать исходный массив из texfile? –

+0

@AhashanAlamSojib см. Https://stackoverflow.com/questions/3518778/how-to-read-csv-into-record-array-in-numpy – atomh33ls

0

У меня есть способ сделать это с помощью операции просто filename.write(). Он отлично работает для меня, но я имею дело с массивами, имеющими ~ 1500 элементов данных.

У меня в основном просто есть петли, чтобы перебирать файл и записывать его в выходной пункт по строке в выводе стиля 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") 

Операторы if и elif используются для добавления запятых между элементами данных. По какой-то причине, они удаляются при чтении файла в виде массива nd. Моя цель состояла в том, чтобы вывести файл как csv, поэтому этот метод помогает справиться с этим.

Надеюсь, это поможет!