【问题标题】:Faster way to convert list of objects to numpy array将对象列表转换为 numpy 数组的更快方法
【发布时间】:2020-08-12 15:57:20
【问题描述】:

我正在尝试通过使用 numpy 数组删除 for 循环和列表理解来优化我的代码。 一般来说,代码的执行现在更快了,但是有一件事情让我很困扰:将我的包含大约 110000 个元素的列表转换为一个 numpy 数组需要程序运行时的大部分时间(5 到 7 秒,只是为了初始化一个数组!)

我有这个

rec = np.array(records)

其中records是一个对象列表。

是否可以加快这个numpy数组的创建速度?

【问题讨论】:

  • 为什么要先创建一个列表,然后将其转换为一个 numpy 数组,如果可能的话,创建一个 numpy 数组?
  • 记录从何而来?
  • 不可能直接创建一个numpy数组,因为数据来自django中的sqlite数据库,所以我得到的记录在QuerySet中......
  • 这些记录是什么样的?

标签: python arrays numpy


【解决方案1】:

如果您的列表是一维的,则使用 np.fromiter() 比使用典型的 np.array() 更快。 大小为 10000 的整数列表的基准测试:

a = [1,2,3,4,5,6,7,8,9,10]*1000

%timeit np.array(a,dtype=np.int32)
456 µs ± 7.16 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit np.fromiter(a,dtype=np.int32,count=10000)
242 µs ± 6.65 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

【讨论】:

  • 由于速度差异如此之大,我很惊讶 np 不检查 arg 是否为列表/元组并在内部调用 fromiter(count=len(a))。类型检查加上 len 不能超过一微秒。但对于典型的小列表来说,这可能不值得
【解决方案2】:

python 存储对象(例如记录中的项目)的方式与 numpy 不同。因此,为了创建numpy数组,需要访问每个元素,然后进行转换。

正如@anmol_uppoal 的评论所暗示的,您应该从一开始就创建一个 numpy 数组。例如

rec = np.zeros((SIZE_OF_ARRAY,))
# Set values of rec in the same way you created records, for instance
for i in range(100):
    rec[i] = i+1

进一步优化将与数据的来源相关联——如果来自文件,请尝试以 numpy 格式而不是文本格式存储。如果是数据库,请考虑保存二进制值(但这在很大程度上取决于应用程序的其余部分)

【讨论】:

    【解决方案3】:

    读取数据时,一般不会以 numpy 数组的形式出现。具有绑定 java 或 python 的 netcdf 库,用于处理 HDF5 或变体中的多变量、多文件数据集。它使用内部优化的数组类型,而不是numpy类型,所以转换是不可避免的。

    例如,从 netcdf 数据集转换需要几分钟时间。 逐步计时表明这只是需要时间的转换

    with CodeTimer("convert np.array"): tcc_obs = np.asarray(tcc_obs)
    

    对于一组形状:(725, 759, 96) ~53 M 个元素 代码块“转换 np.array”耗时:161 秒

    如果有人有办法让它变得更好。从逻辑上讲,最好用布尔数组对 netcdf 变量进行子集化,然后转换一个较小的数组,但是代码使用一些 numpy 函数作为 isin 在两个表中查找公共索引,这对我来说没有等效的 python 数组。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-08
      • 1970-01-01
      • 2015-09-03
      • 2019-02-26
      • 2021-12-30
      相关资源
      最近更新 更多