【问题标题】:Numpy - automatic implicit conversion of np.arrays into listsNumpy - np.arrays 到列表的自动隐式转换
【发布时间】:2016-05-07 17:18:34
【问题描述】:

我正在尝试制作其他 numpy.array'snumpy.array,用于蒙特卡洛模拟。我想获取数组的一个元素(另一个 1d 数组)并对其执行一些函数,该函数返回该数组的一个子部分,然后重新分配它。 原来所有数组的长度都相同,这似乎是导致问题的原因。

我想做:例如

c1 = np.array([np.array(xi) for xi in [[1,2],[1],[1,3]]])
c1[2] = np.array([5])

效果很好:

array([array([1, 2]), array([1]), array([5])], dtype=object)

当我进行使所有子数组保持相同长度的变换时,我得到了相同类型的结构。

c2 = np.array([np.array(xi) for xi in [[1,2],[1],[1,3]]])
c2[1] = np.array([4,5])

给予

array([array([1, 2]), array([4, 5]), array([1, 3])], dtype=object).

反而会发生:例如

当我启动所有长度相同的数组时,它们会从np.arrays 转换为lists

c3 = np.array([np.array(xi) for xi in [[1,2],[1,2],[1,4]]])

给了

array([[1, 2], [1, 2], [1, 4]]).

现在如果我尝试调整其中一个列表的长度

c3[1] = np.array([5])

我开始直播

array([[1, 2], [5, 5], [1, 4]])

当我想要的时候

array([array([1, 2]), array([5]), array([1, 4])])

性能问题

这都是为了蒙特卡洛模拟,通常我希望处理一个包含大约 10000 个子数组的数组,其中每个子数组是一个包含大约 1000 个元素(浮点数)的数组。我一直在使用 numpy,因为它的随机数生成速度非常快,并且它对于矢量化函数具有出色的性能,特别是我想最终对这些函数(np.cumsum)和其他一些更深奥的函数执行某种累积和。我可以用列表来做这种事情,但它花了大约 20 倍的时间,并且我希望尽可能地进行优化。

非常感谢。

【问题讨论】:

  • 你测试过np.array列表的性能,而不是np.array的np.array?
  • 我建议重新考虑这种方法。不同长度的数组看起来很奇怪、不方便并且可能很慢。
  • @kennytm 我还没有测试过它的性能,因为我正在通过以下方式使用np.insertnp.insert(np.array([many_np_arrays]), 0, x0, axis=1).cumsum(axis=1)) 其中x0 是一组初始条件,然后我转使用.cumsum 将这些转换为累积总和。使用 np.insert 添加初始条件非常有用,而不是先创建 for loop 然后再执行某种 x0.append(etc)。本质上,我还想保留np.arrays 的功能。我希望这很清楚。
  • @ev-br 我正在考虑使用pandas dataframe,然后进行行和列操作,但担心性能速度,因为要施加我想要的边界条件,我需要做很多行明智的搜索算法,我担心可能没有很好地矢量化,当我执行这些行时,我不知道它们将被视为什么类型的对象(listnp.arraypd.series 等?) .

标签: python arrays list numpy implicit-conversion


【解决方案1】:

numpy 不允许你改变 np.arrays 的形状 np.arrays:

>>> c3 = np.array([np.array(xi) for xi in [[1,2],[1,2],[1,4]]])
>>> c4 = np.array([c3[:1],np.array([5]), c3[2:]])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: could not broadcast input array from shape (2) into shape (1)

你可以用dtype=np.ndarry代替np.empty

>>> ourList =  [[1,2],[1,2],[1,4]]
>>> c3 = np.empty(len(ourList), dtype=np.ndarray)
>>> for i in xrange(len(ourList)):
>>>     c3[i] = np.array(outList[i])
>>> c3
array([array([1, 2]), array([1, 2]), array([1, 4])], dtype=object)
>>> c3[1] = np.array([5])
>>> c3
array([array([1, 2]), array([5]), array([1, 4])], dtype=object)

这是你要找的吗?

您可能只想输入一个零或一些不会影响模拟的巨大负数/正数:

>>> c3 = np.array([np.array(xi) for xi in [[1,2],[1,2],[1,4]]])
>>> c3[1] = np.array([5])
>>> c3
array([[1, 2],
       [5, 5],
       [1, 4]])
>>> c3[1][1] = -9999999
>>> c3
array([[       1,        2],
       [       5, -9999999],
       [       1,        4]])

【讨论】:

  • 请注意,它会将dtype=np.array 变成dtype=object。这种数组包含指向任何类型对象的指针;
  • 该解决方案正如我所愿!我的意思是我必须比我最初设想的多做几行代码和一些额外的连接/嵌套操作(只有几个!),但现在我看到的性能提高了 40 倍以上最初的listlists 方法,而我最初的np.arraylists 方法(上面问题中的概述)只提高了20 倍(我只说......)。谢谢@Kenneth
  • 尝试c3[...] = ourList填充对象数组。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-19
  • 1970-01-01
相关资源
最近更新 更多