【问题标题】:Initialise numpy array of unknown length初始化未知长度的numpy数组
【发布时间】:2012-04-24 16:50:30
【问题描述】:

我希望能够即时“构建”一个 numpy 数组,我事先不知道这个数组的大小。

例如我想做这样的事情:

a= np.array()
for x in y:
     a.append(x)

这将导致 a 包含 x 的所有元素,显然这是一个微不足道的答案。我只是好奇这是否可能?

【问题讨论】:

  • 可能更有效的方法是分配一些大数组,并在每次达到容量时将其大小加倍。

标签: python arrays numpy


【解决方案1】:

构建一个 Python 列表并将其转换为 Numpy 数组。每次追加 + O(n) 转换为数组需要平均 O(1) 时间,总共需要 O(n)。

    a = []
    for x in y:
        a.append(x)
    a = np.array(a)

【讨论】:

  • 或者更好的是:a = np.array([x for x in y]);或者只是a = np.array(list(y))
【解决方案2】:

你可以这样做:

a = np.array([])
for x in y:
    a = np.append(a, x)

【讨论】:

  • 每次追加都需要线性时间。
  • 这种方法在每次追加时复制数组,即 O(sum(range(n)))。在我的笔记本电脑上,这种方法比@larsman 的方法慢 42 倍:按照 larsmans 方法构建一个列表恰好需要 1000 个循环,最好是 3:1.53 ms per loop。按照这个方法,我需要 10 个循环,最好的 3 个:每个循环 64.8 毫秒。
  • 代码应该是可读的,而不是快的,除非速度是你的瓶颈。为什么要优化只运行一次的代码?
  • 很好的评论@AlexGaudio。我真的不知道。谢谢!
【解决方案3】:

由于 y 是可迭代的,我真的不明白为什么要调用 append:

a = np.array(list(y))

可以,而且速度更快:

import timeit

print timeit.timeit('list(s)', 's=set(x for x in xrange(1000))')
# 23.952975494633154

print timeit.timeit("""li=[]
for x in s: li.append(x)""", 's=set(x for x in xrange(1000))')
# 189.3826994248866

【讨论】:

    【解决方案4】:

    对于后代,我认为这样更快:

    a = np.array([np.array(list()) for _ in y])
    

    您甚至可以传入一个生成器(即 [] -> ()),在这种情况下,内部列表永远不会完全存储在内存中。


    回复下面的评论:

    >>> import numpy as np
    >>> y = range(10)
    >>> a = np.array([np.array(list) for _ in y])
    >>> a
    array([array(<type 'list'>, dtype=object),
           array(<type 'list'>, dtype=object),
           array(<type 'list'>, dtype=object),
           array(<type 'list'>, dtype=object),
           array(<type 'list'>, dtype=object),
           array(<type 'list'>, dtype=object),
           array(<type 'list'>, dtype=object),
           array(<type 'list'>, dtype=object),
           array(<type 'list'>, dtype=object),
           array(<type 'list'>, dtype=object)], dtype=object)
    

    【讨论】:

    • 我在这里做了一个改变:list(_),效果很好
    • 要明确@javadba,你不需要这样做——我敢肯定有一些 Pythonistas 会冒犯 :)
    • 这不是风格问题。如果没有列表(_),它甚至在我认为 y 本身就是一个数组的情况下最终都不起作用
    • OP 说“这将导致 a 包含 x 的所有元素”,所以你确实需要做 list(_)
    【解决方案5】:
    a = np.empty(0)
    for x in y:
        a = np.append(a, x)
    

    【讨论】:

    • 当 x 具有非标量维度时,这将不起作用。例如,如果 x = np.ones((3,5)),就会失败。
    【解决方案6】:

    我写了一个小实用函数。 (上面的大多数答案都很好。我觉得这看起来更好)

    def np_unknown_cat(acc, arr):
      arrE = np.expand_dims(arr, axis=0)
      if acc is None:
        return arrE
      else:
        return np.concatenate((acc, arrE))
    

    上面的函数可以如下使用:

    acc = None  # accumulator
    arr1 = np.ones((3,4))
    acc = np_unknown_cat(acc, arr1)
    arr2 = np.ones((3,4))
    acc = np_unknown_cat(acc, arr2)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-01-25
      • 1970-01-01
      • 2016-05-03
      • 2019-02-28
      • 2014-12-04
      • 1970-01-01
      • 2013-06-24
      相关资源
      最近更新 更多