Интересно, как правильно сохранять и загружать numpy.array
данные. В настоящее время использую numpy.savetxt()
метод. Например, если у меня есть массив markers
, который выглядит так:
Я пытаюсь спасти это с помощью:
numpy.savetxt('markers.txt', markers)
В другом скрипте я пытаюсь открыть ранее сохраненный файл:
markers = np.fromfile("markers.txt")
И вот что я получаю ...
Сохраненные данные сначала выглядят так:
0.000000000000000000e+00
0.000000000000000000e+00
0.000000000000000000e+00
0.000000000000000000e+00
0.000000000000000000e+00
0.000000000000000000e+00
0.000000000000000000e+00
0.000000000000000000e+00
0.000000000000000000e+00
0.000000000000000000e+00
Но когда я сохраняю только что загруженные данные тем же методом, т.е. numpy.savetxt()
это выглядит так:
1.398043286095131769e-76
1.398043286095288860e-76
1.396426376485745879e-76
1.398043286055061908e-76
1.398043286095288860e-76
1.182950697433698368e-76
1.398043275797188953e-76
1.398043286095288860e-76
1.210894289234927752e-99
1.398040649781712473e-76
Что я делаю не так? PS других "закулисных" операций, которые я выполняю, нет. Просто сохранение и загрузка, вот что я получаю. Заранее спасибо.
np.save()
иnp.load()
.scipy.io.savemat
иscipy.io.loadmat
.fromfile
чтения данные как двоичные.loadtxt
правильное соединение сsavetxt
. Посмотрите документацию по функциям.Ответы:
Самый надежный способ, который я нашел для этого, - использовать
np.savetxt
with,np.loadtxt
а не,np.fromfile
который лучше подходит для двоичных файлов, написанных с помощьюtofile
.np.fromfile
Иnp.tofile
методы записи и чтения двоичных файлов , тогда какnp.savetxt
пишет текстовый файл. Так, например:In [1]: a = np.array([1, 2, 3, 4]) In [2]: np.savetxt('test1.txt', a, fmt='%d') In [3]: b = np.loadtxt('test1.txt', dtype=int) In [4]: a == b Out[4]: array([ True, True, True, True], dtype=bool)
Или:
In [5]: a.tofile('test2.dat') In [6]: c = np.fromfile('test2.dat', dtype=int) In [7]: c == a Out[7]: array([ True, True, True, True], dtype=bool)
Я использую первый метод, даже если он медленнее и создает файлы большего размера (иногда): двоичный формат может зависеть от платформы (например, формат файла зависит от порядка байтов в вашей системе).
Для массивов NumPy существует платформенно-независимый формат, который можно сохранять и читать с помощью
np.save
иnp.load
:In [8]: np.save('test3.npy', a) # .npy extension is added if not given In [9]: d = np.load('test3.npy') In [10]: a == d Out[10]: array([ True, True, True, True], dtype=bool)
источник
.npy
файлы (например, созданные с помощьюnp.save()
) не зависят от платформы, их можно компактнее и быстрее создавать, чем текстовые файлы.np.savez
если вы хотите, чтобы вывод был сжат.np.savez
сохраняет несколько массивов несжатыми -np.savez_compressed
буду их сжимать -np.save_compressed
пока нет . См. Docs.scipy.org/doc/numpy-1.15.1/reference/routines.io.htmlnp.save('data.npy', num_arr) # save new_num_arr = np.load('data.npy') # load
источник
pickle
?x = db["x"]
помощьюy = db["y"]
?array.shape
и()
возвращаюсь.np.fromfile()
имеетsep=
аргумент ключевого слова:Значение по умолчанию
sep=""
означает, что онnp.fromfile()
пытается прочитать его как двоичный файл, а не как текстовый файл, разделенный пробелами, поэтому вы получите обратно бессмысленные значения. Если вы используетеnp.fromfile('markers.txt', sep=" ")
то получите желаемый результат.Однако, как указывали другие,
np.loadtxt()
это предпочтительный способ преобразования текстовых файлов в массивы numpy, и, если файл не должен быть удобочитаемым, обычно лучше вместо этого использовать двоичные форматы (например,np.load()
/np.save()
).источник
pickle
?Для краткого ответа используйте
np.save
иnp.load
. Их преимущества в том, что они созданы разработчиками библиотеки numpy и уже работают (плюс, вероятно, уже хорошо оптимизированы), напримерimport numpy as np from pathlib import Path path = Path('~/data/tmp/').expanduser() path.mkdir(parents=True, exist_ok=True) lb,ub = -1,1 num_samples = 5 x = np.random.uniform(low=lb,high=ub,size=(1,num_samples)) y = x**2 + x + 2 np.save(path/'x', x) np.save(path/'y', y) x_loaded = np.load(path/'x.npy') y_load = np.load(path/'y.npy') print(x is x_loaded) # False print(x == x_loaded) # [[ True True True True True]]
Расширенный ответ:
В конце концов, это действительно зависит от ваших потребностей, потому что вы также можете сохранить его в удобочитаемом формате (см. Дамп массива NumPy в файл csv ) или даже с другими библиотеками, если ваши файлы очень большие (см. Этот лучший способ сохранить массивы numpy на диске для расширенного обсуждения).
Однако (делая расширение, поскольку вы используете слово «правильно» в своем вопросе) я все еще думаю, что использование функции numpy из коробки (и большей части кода!), Скорее всего, удовлетворит большинство потребностей пользователей. Самая главная причина в том, что это уже работает . Попытка использовать что-то еще по любой другой причине может привести вас к неожиданно ДЛИННОЙ кроличьей норе, чтобы выяснить, почему это не работает, и заставить его работать.
Возьмем, к примеру, попытку спасти рассолом. Я попробовал это просто для удовольствия, и мне потребовалось не менее 30 минут, чтобы понять, что pickle не спасет мои вещи, если я не открою и не прочитаю файл в байтовом режиме с помощью
wb
. Потребовалось время, чтобы погуглить, попробовать что-то, понять сообщение об ошибке и т. Д. Небольшая деталь, но тот факт, что мне уже требовалось открыть файл, усложнял ситуацию неожиданным образом. Чтобы добавить, что мне потребовалось перечитать это (что, кстати, немного сбивает с толку) Разница между режимами a, a +, w, w + и r + во встроенной функции открытия?.Поэтому, если есть интерфейс, который соответствует вашим потребностям, используйте его, если у вас нет ( очень ) веской причины (например, совместимость с Matlab или по какой-то причине вы действительно хотите прочитать файл, а печать на python действительно не соответствует вашим потребностям, что может быть сомнительным). Кроме того, скорее всего, если вам нужно оптимизировать его, вы узнаете позже (вместо того, чтобы тратить годы на отладку бесполезных вещей, таких как открытие простого файла numpy).
Так что используйте интерфейс / numpy . Это может быть не идеально, скорее всего, это нормально, особенно для библиотеки, которая существует так долго, как numpy.
Я уже потратил кучу времени на сохранение и загрузку данных с помощью numpy, так что получайте удовольствие, надеюсь, это поможет!
import numpy as np import pickle from pathlib import Path path = Path('~/data/tmp/').expanduser() path.mkdir(parents=True, exist_ok=True) lb,ub = -1,1 num_samples = 5 x = np.random.uniform(low=lb,high=ub,size=(1,num_samples)) y = x**2 + x + 2 # using save (to npy), savez (to npz) np.save(path/'x', x) np.save(path/'y', y) np.savez(path/'db', x=x, y=y) with open(path/'db.pkl', 'wb') as db_file: pickle.dump(obj={'x':x, 'y':y}, file=db_file) ## using loading npy, npz files x_loaded = np.load(path/'x.npy') y_load = np.load(path/'y.npy') db = np.load(path/'db.npz') with open(path/'db.pkl', 'rb') as db_file: db_pkl = pickle.load(db_file) print(x is x_loaded) print(x == x_loaded) print(x == db['x']) print(x == db_pkl['x']) print('done')
Некоторые комментарии к тому, что я узнал:
np.save
как и ожидалось, это уже хорошо сжимает его (см. https://stackoverflow.com/a/55750128/1601580 ), работает из коробки без открытия файла. Чистый. Легко. Эффективно. Используй это.np.savez
использует несжатый формат (см. документацию )Save several arrays into a single file in uncompressed
.npzformat.
Если вы решите использовать это (вас предупредили, что нужно отказаться от стандартного решения, так что ожидайте ошибок!), вы можете обнаружить, что вам нужно использовать имена аргументов для его сохранения, если вы не хотите используйте имена по умолчанию. Так что не используйте это, если первый уже работает (или какие-либо работы используют это!)hdf5
для больших файлов. Круто! https://stackoverflow.com/a/9619713/1601580Обратите внимание, что это не исчерпывающий ответ. Но для других ресурсов проверьте это:
np.save
): Сохраните массив Numpy с помощью Pickleисточник