Làm thế nào để lưu và tải dữ liệu numpy.array () đúng cách?


104

Tôi tự hỏi, làm thế nào để lưu và tải numpy.array dữ liệu đúng cách. Hiện tại tôi đang sử dụng numpy.savetxt()phương pháp. Ví dụ: nếu tôi có một mảng markers, trông giống như sau:

nhập mô tả hình ảnh ở đây

Tôi cố gắng lưu nó bằng cách sử dụng:

numpy.savetxt('markers.txt', markers)

Trong tập lệnh khác, tôi cố gắng mở tệp đã lưu trước đó:

markers = np.fromfile("markers.txt")

Và đó là những gì tôi nhận được ...

nhập mô tả hình ảnh ở đây

Dữ liệu đã lưu đầu tiên trông giống như sau:

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

Nhưng khi tôi lưu dữ liệu vừa tải bằng cách sử dụng cùng một phương pháp, tức là. numpy.savetxt()nó trông như thế này:

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

Tôi đang làm gì sai? PS không có hoạt động "hậu trường" nào khác mà tôi thực hiện. Chỉ cần lưu và tải, và đó là những gì tôi nhận được. Cảm ơn bạn trước.


Đầu ra của tệp văn bản là gì? Tại sao không chỉ ghi vào tệp CSV?

4
Bạn có cần lưu và tải dưới dạng tệp văn bản mà con người có thể đọc được không? Nó sẽ nhanh hơn (và các tệp sẽ nhỏ gọn hơn) nếu bạn lưu / tải các tệp nhị phân bằng cách sử dụng np.save()np.load().
ali_m

Cảm ơn vì lời khuyên của bạn. Nó đã giúp đỡ. Tuy nhiên, bạn có thể giải thích lý do tại sao nó lại như vậy và có cách nào cho phép lưu dữ liệu ở định dạng * .txt và tải nó mà không đau đầu không? Ví dụ, khi một người muốn làm việc với matlab, java hoặc các công cụ / ngôn ngữ khác.
bluevoxel

3
Để chuyển mảng đến / từ MATLAB, bạn có thể sử dụng scipy.io.savematscipy.io.loadmat.
ali_m

2
Giá trị mặc định fromfilelà đọc dữ liệu dưới dạng nhị phân. loadtxtlà ghép nối chính xác với savetxt. Nhìn vào tài liệu chức năng.
hpaulj

Câu trả lời:


146

Cách đáng tin cậy nhất mà tôi đã tìm thấy để làm điều này là sử dụng np.savetxtvới np.loadtxtvà khôngnp.fromfile cái nào phù hợp hơn với các tệp nhị phân được viết bằng tofile. Các phương thức np.fromfilenp.tofileghi và đọc các tệp nhị phân trong khi np.savetxtghi một tệp văn bản. Ví dụ:

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)

Hoặc là:

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)

Tôi sử dụng phương pháp cũ ngay cả khi nó chậm hơn và tạo ra các tệp lớn hơn (đôi khi): định dạng nhị phân có thể phụ thuộc vào nền tảng (ví dụ: định dạng tệp phụ thuộc vào khả năng sử dụng của hệ thống của bạn).

Có một định dạng độc lập với nền tảng cho mảng NumPy, có thể được lưu và đọc với 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
.npyfile (ví dụ như tạo ra bởi np.save()) nền tảng độc lập, và sẽ nhỏ gọn hơn và nhanh hơn để tạo ra tập tin văn bản hơn.
ali_m

2
cũng np.saveznhư nếu bạn muốn nén đầu ra.
tegan

3
@tegan np.savezlưu một số mảng không nén - np.savez_compressedsẽ nén chúng - vẫn chưa có np.save_compressed. Xem docs.scipy.org/doc/numpy-1.15.1/reference/routines.io.html
Brian Burns

1
Cảm ơn xnx Tôi đã có cùng một vấn đề (với dtype float) sử dụng np.savetxt với np.loadtxt giải quyết nó
Yogesh

Tôi đã gặp sự cố với bộ nhớ lưu dữ liệu lớn hơn 2GB. Nhờ xnx, vấn đề đã được giải quyết bằng cách sử dụng a.tofile và np.fromfile.
Azr

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

có vấn đề gì với việc sử dụng picklekhông?
Charlie Parker

Ví dụ: để chúng tôi có thể tải dữ liệu với như x = db["x"]sau y = db["y"]?
Charlie Parker

3

np.fromfile()sep=đối số từ khóa:

Dấu phân cách giữa các mục nếu tệp là tệp văn bản. Dấu phân cách trống (“”) có nghĩa là tệp phải được coi là tệp nhị phân. Dấu cách (””) trong dấu phân cách khớp với không hoặc nhiều ký tự khoảng trắng. Dấu phân tách chỉ bao gồm các khoảng trắng phải khớp với ít nhất một khoảng trắng.

Giá trị mặc định của sep=""nghĩa là np.fromfile()cố gắng đọc nó dưới dạng tệp nhị phân chứ không phải tệp văn bản được phân tách bằng dấu cách, vì vậy bạn sẽ nhận lại các giá trị vô nghĩa. Nếu bạn sử dụng np.fromfile('markers.txt', sep=" ")bạn sẽ nhận được kết quả mà bạn đang tìm kiếm.

Tuy nhiên, như những người khác đã chỉ ra, đây np.loadtxt()là cách ưu tiên để chuyển đổi tệp văn bản thành mảng không có hạt, và trừ khi tệp cần phải được con người đọc được thì tốt hơn nên sử dụng các định dạng nhị phân thay thế (ví dụ np.load()/ np.save()).


có vấn đề gì với việc sử dụng picklekhông?
Charlie Parker

0

Đối với một câu trả lời ngắn, bạn nên sử dụng np.savenp.load. Ưu điểm của những điều này là chúng được tạo ra bởi các nhà phát triển của thư viện numpy và chúng đã hoạt động (cộng thêm có thể đã được tối ưu hóa độc đáo) ví dụ:

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

Câu trả lời mở rộng:

Cuối cùng, nó thực sự phụ thuộc vào nhu cầu của bạn vì bạn cũng có thể lưu nó ở định dạng con người có thể đọc được (xem phần này Kết xuất mảng NumPy vào tệp csv ) hoặc thậm chí với các thư viện khác nếu tệp của bạn cực kỳ lớn (xem phần này cách tốt nhất để bảo vệ mảng numpy trên đĩa cho một cuộc thảo luận mở rộng).

Tuy nhiên, (mở rộng vì bạn sử dụng từ "đúng cách" trong câu hỏi của mình) Tôi vẫn nghĩ rằng việc sử dụng hàm numpy out of the box (và hầu hết mã!) Rất có thể sẽ đáp ứng hầu hết các nhu cầu của người dùng. Lý do quan trọng nhất là nó đã hoạt động . Cố gắng sử dụng thứ khác vì bất kỳ lý do nào khác có thể đưa bạn vào một lỗ thỏ DÀI bất ngờ để tìm ra lý do tại sao nó không hoạt động và buộc nó hoạt động.

Lấy ví dụ cố gắng cứu nó bằng dưa chua. Tôi đã thử điều đó chỉ để giải trí và tôi đã mất ít nhất 30 phút để nhận ra rằng dưa chua sẽ không lưu nội dung của tôi trừ khi tôi mở và đọc tệp ở chế độ byte với wb. Mất thời gian vào google, thử điều gì đó, hiểu thông báo lỗi vv ... Chi tiết nhỏ nhưng thực tế là nó đã yêu cầu tôi mở một tệp phức tạp theo những cách không mong muốn. Để nói thêm rằng nó yêu cầu tôi đọc lại điều này (btw hơi khó hiểu) Sự khác biệt giữa các chế độ a, a +, w, w + và r + trong hàm mở tích hợp sẵn?.

Vì vậy, nếu có một giao diện đáp ứng nhu cầu của bạn, hãy sử dụng nó trừ khi bạn có ( rất ) lý do chính đáng (ví dụ: khả năng tương thích với matlab hoặc vì lý do nào đó bạn thực sự muốn đọc tệp và in bằng python thực sự không đáp ứng được nhu cầu của bạn, điều này có thể nghi vấn). Hơn nữa, rất có thể nếu bạn cần tối ưu hóa nó, bạn sẽ phát hiện ra sau đó (thay vì mất nhiều thời gian để gỡ lỗi những thứ vô dụng như mở một tệp numpy đơn giản).

Vì vậy, hãy sử dụng giao diện / numpy cung cấp . Nó có thể không hoàn hảo nhưng rất có thể nó vẫn ổn, đặc biệt là đối với một thư viện đã tồn tại lâu như vậy.

Tôi đã sử dụng rất nhiều cách để lưu và tải dữ liệu với numpy nên hãy vui vẻ với nó, hy vọng nó sẽ hữu ích!

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

Một số nhận xét về những gì tôi học được:

  • np.savenhư mong đợi, điều này đã nén nó tốt (xem https://stackoverflow.com/a/55750128/1601580 ), hoạt động hiệu quả mà không cần mở tệp nào. Dọn dẹp. Dễ dàng. Có hiệu quả. Sử dụng nó.
  • np.savezsử dụng định dạng không nén (xem tài liệu ) Save several arrays into a single file in uncompressed .npz format.Nếu bạn quyết định sử dụng định dạng này (bạn đã được cảnh báo là không sử dụng giải pháp tiêu chuẩn vì vậy sẽ có lỗi!), bạn có thể phát hiện ra rằng bạn cần sử dụng tên đối số để lưu nó, trừ khi bạn muốn sử dụng các tên mặc định. Vì vậy, không sử dụng cái này nếu cái đầu tiên đã hoạt động (hoặc bất kỳ tác phẩm nào sử dụng cái đó!)
  • Pickle cũng cho phép thực thi mã tùy ý. Một số người có thể không muốn sử dụng nó vì lý do bảo mật.
  • Các tệp có thể đọc được của con người rất tốn kém để tạo ra, v.v. Có lẽ không đáng.
  • có một cái gì đó được gọi hdf5cho các tệp lớn. Mát mẻ! https://stackoverflow.com/a/9619713/1601580

Lưu ý rằng đây không phải là một câu trả lời đầy đủ. Nhưng đối với các tài nguyên khác, hãy kiểm tra điều này:

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.