【问题标题】:Obtain lengths of vectors without loading multiple .npy files在不加载多个 .npy 文件的情况下获取向量的长度
【发布时间】:2018-10-19 09:42:41
【问题描述】:

我有大约 2000 个 .npy 文件,每个文件代表一个一维浮点向量,其中包含 100,000 到 1,000,000 个条目(这两个数字在未来都会大幅增长)。对于每个文件,我想要它包含的向量的长度。以下选项是可能的,但耗时:

lengths = [numpy.shape(numpy.load(whatever))[0] for whatever in os.listdir(some_dir)]

问题: 导出这个向量长度列表的最有效/最快的方法是什么?当然,我应该能够直接从文件大小开始工作——但是最好的方法是什么?

【问题讨论】:

    标签: python file numpy


    【解决方案1】:

    使用 memmapped 文件将大大加快速度。 通过对文件进行内存映射,numpy 仅加载标题以获取数组形状和数据类型,而实际的数组数据保留在磁盘上,直到需要为止。

    import numpy as np 
    # Load files using memmap
    data = [np.load(f, mmap_mode='r')) for f in os.listdir(some_dir)]
    # Checking your assumptions never hurts
    assert (d.ndim == 1 for d in data).all()  
    
    lengths = [d.shape[0] for d in data]
    

    edit 您需要加载文件头而不是直接使用文件大小的原因是npy 文件的头不一定是固定长度。尽管对于没有字段或字段名的一维数组,它可能不会改变(参见https://www.numpy.org/devdocs/reference/generated/numpy.lib.format.html)。

    【讨论】:

      【解决方案2】:

      你可以试试这个

      import os
      
      fileinfo = os.stats('1darray.npy')
      

      数组长度

      a = os.stat('1darray.npy')
      int((a.st_size - 128)/itemsize) 
      

      128 是 npy 文件保存在操作系统目录中时所占用的额外大小。任何 numpy 数组的实际字节大小都可以在 array.nbytes 中找到。所以a.st_size - 128 = array.nbytesarray.bytes/array.itemsize = array.size = array lenght

      其中itemsize = 2 如果数组是float 16 位类型,4 如果类型是浮点32 位和8 如果数组是float 64 位类型

      这是一个演示

      import numpy as np
      import os
      array = np.arange(12, dtype=np.float64)
      print(a.itemsize) # >> gives 8 for float 64 bit
      np.save('1darray.npy', array)
      a = os.stat('1darray.npy')
      length = int((a.st_size - 128)/8) # >> gives 12 which is equal to array.size
      

      所以你必须知道保存的 numpy npy 文件的 dtype 是什么

      因此,对于您的情况,您可以这样做

      lengths = [(os.stat(whatever).st_size - 128)/8 for whatever in os.listdir(some_dir)] 
      

      假设 npy 数组的 dtypes 是 float64

      【讨论】:

      • 128这个数字是多少,稳定性如何? (例如跨 numpy 版本)
      • 这是一个额外大小的文件文件,当保存在操作系统目录中时,除了原始的 numpy 数组。您可以使用 nbytes 检查任何 numpy 数组的大小,例如,如果 a 是一个 numpy 数组,则 a.nbytes 给出它的大小。 @DanielMoskovich
      • 这里有文档 (docs.scipy.org/doc/numpy/reference/generated/…) ,技术上 128 是可变的,头中的字节 9 和 10 指定大小,它将始终被填充,使得头的总大小可以被 64 整除. 在大多数实际应用中,这似乎产生 128。
      猜你喜欢
      • 2011-12-02
      • 1970-01-01
      • 2013-12-01
      • 2021-12-21
      • 1970-01-01
      • 2010-12-19
      • 2017-12-20
      • 1970-01-01
      相关资源
      最近更新 更多