Как записать многомерный массив в текстовый файл? - PullRequest
96 голосов
/ 10 сентября 2010

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

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

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

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

TypeError: float argument required, not numpy.ndarray

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

Ответы [ 8 ]

177 голосов
/ 10 сентября 2010

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

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

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

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

Например, этот (двумерный массив) работает нормально

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

Хотя то же самое не получится (с довольно неинформативной ошибкой: TypeError: float argument required, not numpy.ndarray) для трехмерного массива:

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

Один из обходных путей - просто разбить трехмерный (или больший) массив на двухмерные срезы.Например,

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 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)
28 голосов
/ 10 сентября 2010

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

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

В отличие от ответа Джо Кингтона, выгода этого в том, что вам не нужно знать исходную форму данных в файле .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()

И, конечно же, вы можете хранить много массивов, используя еще больше ключей.

Так что да - это не будет читаемо вашими глазами, но только для записи и чтения данных потребуется всего две строки, что я считаючестный компромисс.

Посмотрите документы для scipy.io.savemat и scipy.io.loadmat , а также страницу этого учебника: scipy.io File IO Tutorial

7 голосов
/ 09 августа 2013

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

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

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

Хотя вы не знаете, как получить форматирование новой строки.

Редактировать (см. Комментарий Кевина Дж. Блэка здесь ):

Начиная с версии 1.5.0, np.tofile() принимает необязательный параметрnewline='\n', чтобы разрешить многострочный вывод.https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.savetxt.html

3 голосов
/ 10 сентября 2010

Для этого существуют специальные библиотеки.(Плюс оболочки для python)

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

1 голос
/ 10 сентября 2010

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

0 голосов
/ 10 декабря 2018

Рассол лучше всего подходит для этих случаев.Предположим, у вас есть ndarray с именем x_train.Вы можете сбросить его в файл и вернуть обратно, используя следующую команду:

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)
0 голосов
/ 17 марта 2014

У меня есть способ сделать это с помощью простой операции 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, поэтому этот метод помогает справиться с этим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...