numpy.array () 데이터를 올바르게 저장하고로드하는 방법은 무엇입니까?


104

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

내가 뭘 잘못하고 있죠? 추신 : 내가 수행하는 다른 "무대"작업이 없습니다. 저장하고 불러 오기만하면됩니다. 미리 감사드립니다.


텍스트 파일의 출력은 무엇입니까? CSV 파일에 쓰지 않는 이유는 무엇입니까?

4
사람이 읽을 수있는 텍스트 파일로 저장하고로드해야합니까? 그것은 빠를 것이다 (그리고 파일은보다 컴팩트 한 것) 당신이 저장하는 경우 / 사용하여 바이너리 파일을로드 np.save()하고 np.load().
ali_m

조언 고마워. 도움이되었습니다. 그러나 왜 그것이 무엇인지 설명 할 수 있으며 * .txt 형식으로 데이터를 저장하고 두통없이로드 할 수있는 방법이 있다면? 예를 들어, MATLAB, Java 또는 기타 도구 / 언어로 작업하고 싶을 때.
bluevoxel

3
MATLAB으로 /로부터 배열을 전달하려면 scipy.io.savemat및 을 사용할 수 있습니다 scipy.io.loadmat.
ali_m

2
의 기본값 fromfile은 데이터를 바이너리로 읽는 것입니다. loadtxt와 올바른 페어링입니다 savetxt. 함수 문서를보십시오.
hpaulj

답변:


146

내가이 일을 발견하는 가장 신뢰할 수있는 방법은 사용하는 것입니다 np.savetxt함께 np.loadtxt하지 np.fromfile더 나은로 작성된 바이너리 파일에 적합한된다 tofile. np.fromfilenp.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.savenp.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)

47
.npy파일 (예 :에서 생성됨 np.save()) 플랫폼에 독립적이며 텍스트 파일보다 더 작고 빠르게 생성됩니다.
ali_m 2015

2
np.savez출력을 압축하려는 경우 에도 마찬가지 입니다.
tegan

3
@tegan np.savez은 압축되지 않은 여러 배열을 저장 np.savez_compressed합니다-압축합니다- np.save_compressed아직 없습니다 . docs.scipy.org/doc/numpy-1.15.1/reference/routines.io.html
Brian Burns

1
고맙습니다 xnx 나는 np.loadtxt와 함께 np.savetxt를 사용하여 같은 문제 (dtype float와 함께)가 해결되었습니다
Yogesh

2GB 이상의 피클 저장 데이터에 문제가 있습니다. xnx 덕분에 a.tofile 및 np.fromfile을 사용하여 문제가 해결되었습니다.
Azr

47
np.save('data.npy', num_arr) # save
new_num_arr = np.load('data.npy') # load

사용에 문제가 pickle있습니까?
Charlie Parker

예를 들어 x = db["x"]다음 과 같이 데이터를로드 할 수 있도록 y = db["y"]?
Charlie Parker

3

np.fromfile()sep=키워드 인수를 :

파일이 텍스트 파일 인 경우 항목을 구분합니다. 빈 ( "") 구분 기호는 파일이 바이너리로 처리되어야 함을 의미합니다. 구분자의 공백 (””)은 0 개 이상의 공백 문자와 일치합니다. 공백으로 만 구성된 구분 기호는 하나 이상의 공백과 일치해야합니다.

기본값 은 공백으로 구분 된 텍스트 파일이 아닌 이진 파일로 읽으려고 시도하므로 말도 안되는 값을 반환 sep=""한다는 의미입니다 np.fromfile(). 사용 np.fromfile('markers.txt', sep=" ")하면 원하는 결과를 얻을 수 있습니다.

그러나 다른 사람들이 지적했듯이 np.loadtxt()텍스트 파일을 numpy 배열로 변환하는 데 선호되는 방법이며 파일이 사람이 읽을 수 있어야하는 경우가 아니면 일반적으로 바이너리 형식 (예 : np.load()/ np.save()) 을 사용하는 것이 좋습니다 .


사용에 문제가 pickle있습니까?
Charlie Parker

0

짧은 대답을 위해서는 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 함수를 사용하여 대부분의 사용자 요구를 충족시킬 가능성이 가장 높다고 생각합니다. 가장 중요한 이유는 이미 작동 하고 있기 때문입니다 . 다른 이유로 다른 것을 사용하려고하면 예상치 않게 긴 토끼 구멍에 빠지게되어 작동하지 않는 이유를 파악하고 강제로 작동시킬 수 있습니다.

예를 들어 피클을 사용하여 저장하려고합니다. 나는 재미로 그것을 시도했고, .NET을 사용하여 바이트 모드에서 파일을 열고 읽지 않으면 pickle이 내 물건을 저장하지 않는다는 것을 깨닫는 데 적어도 30 분이 걸렸습니다 wb. Google에 시간이 걸렸고, 시도하고, 오류 메시지를 이해하는 등 ... 작은 세부 사항이지만 이미 예기치 않은 방식으로 복잡한 파일을 열어야한다는 사실. 추가하려면 이것을 다시 읽어야합니다 (어떤 btw는 일종의 혼란 스럽습니다) . 내장 개방 기능에서 모드 a, a +, w, w + 및 r + 간의 차이점은 무엇입니까?.

따라서 요구 사항을 충족하는 인터페이스가 있으면 ( 매우 ) 좋은 이유 (예 : matlab과의 호환성 또는 어떤 이유로 파일을 읽고 싶어하고 파이썬으로 인쇄하는 것이 실제로 귀하의 요구를 충족시키지 못합니다. 의심 스러울 수 있습니다). 또한 최적화가 필요한 경우 나중에 확인할 수 있습니다 (간단한 numpy 파일을 여는 것과 같은 쓸모없는 것들을 디버깅하는 데 오랜 시간을 소비하는 대신).

따라서 interface / numpy provide . 완벽하지 않을 수도 있습니다. 특히 오래 동안 주변에 있었던 도서관의 경우에는 좋습니다.

나는 이미 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 .npz을 format.당신은 당신이 원하는하지 않는 한, 그것을 저장 인수 이름을 사용할 필요가 있음을 발견 할 수있다 (당신이 그렇게 버그를 기대합니다! 표준액에서 멀리 갈 경고했다)이 사용하기로 결정한 경우 기본 이름을 사용하십시오. 그러니 첫 번째가 이미 작동한다면 이것을 사용하지 마십시오 (또는 어떤 작품도 그것을 사용합니다!)
  • Pickle은 또한 임의의 코드 실행을 허용합니다. 어떤 사람들은 보안상의 이유로 이것을 사용하지 않을 수 있습니다.
  • 사람이 읽을 수있는 파일은 만드는 데 비용이 많이 듭니다. 아마도 그만한 가치가 없을 것입니다.
  • 라는 무언가가 hdf5큰 파일은. 멋있는! https://stackoverflow.com/a/9619713/1601580

이것은 완전한 대답이 아닙니다. 그러나 다른 리소스의 경우 다음을 확인하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.