【问题标题】:Choose to save data as pickled in numpy array or in list选择将数据保存为 numpy 数组或列表中的腌制数据
【发布时间】:2021-09-21 00:33:34
【问题描述】:

我目前有一个包含大约 700K 元组(4 个整数和 1 个字符串)的列表。列表腌制文件大约需要 160M,从硬盘加载大约需要 1 秒,创建 numpy 对象又需要 1.6 秒,总共大约 2.6 秒

在 numpy.array 对象中列出数据时,没有 dtype=type 声明需要 3.2G 和 2 秒才能加载。虽然在 dtype=object 中是 180Mish,但加载需要 16 秒

有没有更好的方法可以让这些变得更快并且花费不很大的空间?

============================================

这里是使用 h5py 的一些测试结果

元组中的字符串必须进行编码,因此,所有的 int 也将保存为字节数组,最终为 800M...不确定我是否在这里做错了。但只花了大约半秒来加载

如果保存为 numpy.array,字符串部分 dtype 声明为 h5py.string_dtype('utf-8'),它最终为 270M,但加载大约需要 2.4s

====================================

在 numpy.savez 上测试,字符串描述为 S40 = 190M,加载时间 = 0.6 秒

======================================

【问题讨论】:

  • 将整数保存在单独的数组中。
  • 字符串有多长?
  • 还可以考虑使用数据库(例如 SQLite)。
  • 见stackoverflow.com/questions/9619199/…。 Pickle 不是空间的最佳格式,也不是性能的最佳格式(但对于并不总是需要的可移植性非常好)。 NPY/二进制格式要快得多且节省空间。更不用说它们可以与 LZ4 等非常快速的压缩算法结合使用。请注意,非本机类型(即纯 Python 类型)确实应该避免,因为它们速度慢、易操作且繁重(更不用说 GIL 问题了)。
  • 你在制作什么样的数组,对象 dtype 还是结构化的? object dtype 与列表相比几乎没有优势。

标签: python numpy


【解决方案1】:

既然您说您的字符串最多 30 个字符,请使用这样的结构化 dtype:

dtype = [('a', 'i4'), ('b', 'i4'), ('c', 'i4'), ('d', 'i4'), ('e', 'S30')]

那么每条记录都是46字节长,性能应该比dtype=object好很多。

或者,如果您需要一次访问一列,最好将每一列存储在单独的数组中。您可以将它们一起保存为单个 .npz 文件,该文件只是一个 .npy 文件的 Zip 存档,使用 np.savez() 并可选择压缩。

【讨论】:

  • 嗨。很抱歉测试字符串是从 1 到 40,我已经用一些测试结果更新了我的问题。看起来它仍然比列表格式的测试腌制对象大,但在 numpy 中它肯定很快。只是另一个问题,我怎样才能检索到字符串的最大长度?因为您的解决方案要求用最大数字声明 S,否则,超长部分将被截断..
  • @user2625363 是的,如果事先不知道最大字符串长度,您需要遍历所有数据以确定最大字符串长度。一个简单的for 循环就可以了。
猜你喜欢
  • 2015-12-05
  • 2015-05-08
  • 1970-01-01
  • 2023-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
相关资源
最近更新 更多