Python中np.savetxt()与pickle本地化性能对比分析

如题,数据量比较大,想把一个 ndarray 保存到本地,这两种方法和直接 write 到本地性能相比怎么样,我试了下 savetxt()有点慢,请问大家有什么比较好的方法吗


Python中np.savetxt()与pickle本地化性能对比分析
6 回复

试试 Apache Arrow(Apache Parquet Format)


这个问题挺有意思的,np.savetxt()pickle完全是两种不同用途的工具,直接对比“性能”不太合适,因为它们解决的是不同的问题。

简单来说:

  • np.savetxt() 是NumPy提供的函数,专门用于将一维或二维数组保存为人类可读的纯文本文件(如CSV、TXT格式)。它生成的文件你可以用记事本直接打开查看。
  • pickle 是Python标准库的模块,用于序列化(即:将内存中的任意Python对象转换为字节流)和反序列化。它保存的是对象的二进制表示,文件是机器可读的,人直接看是乱码。它可以保存几乎任何Python对象(列表、字典、自定义类的实例、NumPy数组等等),而不仅仅是数组。

所以,选择哪个取决于你的需求:

  1. 如果你只需要保存/加载一个或几个NumPy数组,并且希望文件能被其他程序(如Excel、R)或人直接阅读/编辑,用 np.savetxt() (保存) 和 np.loadtxt() (加载)。

    import numpy as np
    data = np.array([[1, 2, 3], [4, 5, 6]])
    # 保存为文本
    np.savetxt('data.txt', data, delimiter=',', fmt='%d')
    # 从文本加载
    loaded_data = np.loadtxt('data.txt', delimiter=',', dtype=int)
    
  2. 如果你需要保存/加载复杂的Python对象(比如包含多个数组、列表、字典的字典,或者一个机器学习模型),或者你只关心在Python程序之间快速交换数据,不需要人类可读,用 pickle

    import pickle
    import numpy as np
    complex_obj = {
        'array1': np.arange(10),
        'list1': [1, 2, 3],
        'model_params': {'weights': np.random.randn(5, 2)}
    }
    # 保存对象
    with open('data.pkl', 'wb') as f: # 注意是二进制写入 'wb'
        pickle.dump(complex_obj, f)
    # 加载对象
    with open('data.pkl', 'rb') as f: # 注意是二进制读取 'rb'
        loaded_obj = pickle.load(f)
    

关于你提到的“性能”:如果非要比,对于保存单个大型NumPy数组pickle通常更快,文件也更小,因为它是二进制格式。np.savetxt()需要将数字转换成文本字符串,写入文件更大,读写也更慢。但对于跨语言兼容或可读性,文本格式是必须的。

总结:要可读可移植选savetxt,要存复杂对象或追求速度选pickle。

cPickle 了解一下

以前用过这个,据说比 pickle 快

massage pack 了解一下

其实还有一些蹊跷意淫的办法,比如你先 pickle 保存 ndarray 的 dtype size shape 三个属性,然后用 memcpy 直接保存 ndarray 的 data,那是一个 memoryview 对象,你可以用 mmap 或者直接 file.write 保存进文件,读的时候用 np.frombuffer 或者 np.fromstring 读进来后 reshape 一下就好了( frombuffer 的话最后需要 copy 一下,否则当原 buffer 对象失效之后会出问题,当然如果你原 buffer 对象是从 mmap 获得的话那也没事,而且后续对该 ndarray 的修改还能用过 mmap.flush 写回硬盘)

回到顶部