【问题标题】:Multiply two arrays element wise, where one of the arrays has arrays as elements将两个数组元素相乘,其中一个数组将数组作为元素
【发布时间】:2013-11-08 21:22:54
【问题描述】:

我有以下情况,我想将两个数组元素相乘,其中一个数组将数组作为元素:

>>> import numpy as np
>>> base = np.array( [100., 111.,] )
>>> c = np.array( [9., 11.] )
>>> n0 = np.zeros(len(base))
>>> nn = 3 + n0     # This is the gist of a bunch of intermediate operations
>>> grid = [np.ones(i) for i in nn]
>>> base
array([ 100.,  111.])
>>> c
array([  9.,  11.])
>>> nn
array([ 3.,  3.])
>>> grid
[array([ 1.,  1.,  1.]), array([ 1.,  1.,  1.])]

到目前为止,一切看起来都不错。 grid 似乎有两个元素,每个元素长三个。我觉得我应该可以将它与c相乘

>>> a = grid * c
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: operands could not be broadcast together with shapes (2,3) (2) 

这并没有像我希望的那样进行。这个错误是有希望的。我可以做一些换位技巧并得到我的结果:

a = (grid.T * c).T 回溯(最近一次通话最后): 文件“”,第 1 行,在 AttributeError: 'list' 对象没有属性 'T'

这比我预期的更失败。我以为我正在处理一个数组,但我知道我现在有一个列表。我尝试了一些老式的蛮力:

>>> grid_mod = np.array( [np.ones(3), np.ones(3) ] )
>>> grid_mod
array([[ 1.,  1.,  1.],
       [ 1.,  1.,  1.]])
>>> grid_mod * c
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: operands could not be broadcast together with shapes (2,3) (2) 

我确信这会奏效!我注意到我的最后一个元素后面有一个多余的空格,所以我删除了它:

>>> grid_mod2 = np.array( [np.ones(3), np.ones(7)] )
>>> grid_mod2
array([array([ 1.,  1.,  1.]), array([ 1.,  1.,  1.,  1.,  1.,  1.,  1.])], dtype=object)
>>> grid_mod2 * c
array([array([ 9.,  9.,  9.]),
       array([ 11.,  11.,  11.,  11.,  11.,  11.,  11.])], dtype=object)

最后一个按预期工作。

我的问题是:

  1. 如何定义grid 以便结果是数组数组而不是数组列表。
  2. 这一切到底发生了什么?为什么数组末尾的多余空间会给我一个完全不同的结果。
  3. 有没有更 Pythonic 的方式来解决这个问题?

【问题讨论】:

  • 尝试使用grid=np.vstack(grid)并使用二维数组grid
  • 当我做乘法时,这仍然给我一个广播错误。

标签: python arrays numpy


【解决方案1】:

这两段代码产生不同的东西,虽然空格没有作用:

>>> np.array([np.ones(3), np.ones(3)])
array([[ 1.,  1.,  1.],
       [ 1.,  1.,  1.]])

由于列表中的两个数组具有相同的维度,因此将其转换为 2 行 3 列的单个数组。

>>> np.array([np.ones(3), np.ones(7)])
array([array([ 1.,  1.,  1.]), array([ 1.,  1.,  1.,  1.,  1.,  1.,  1.])], dtype=object)

在这种情况下,数组的长度不匹配,因此 numpy 创建了一个长度为两个项目的一维数组,其类型为 object,每个对象都恰好是一个 numpy 数组。

当您将第一个与c 相乘时,您正在尝试将形状为(2, 3) 的数组与形状为(2,) 的数组相乘,而numpy 不知道该怎么做。如果您将c 数组重新整形为具有(2, 1) 的形状,您可以获得您想要的,例如

>>> grid_mod * c[:, np.newaxis]
array([[  9.,   9.,   9.],
       [ 11.,  11.,  11.]])

当您将第二个与c 相乘时,您正在尝试将两个形状为(2,) 的数组相乘,因此numpy 可以毫无问题地进行元素乘法。而且由于数组中的每个项目本身都是一个数组,因此当您尝试将其乘以标量时,numpy 也知道该怎么做。虽然这确实有效,但它比以前的方法慢得多,对于 10000 行数组大约慢 100 倍:

c = np.random.rand(10000)
a = np.random.rand(10000, 3)
b = np.empty((10000,), dtype=object)
for j in xrange(10000):
    b[j] = a[j]

%timeit a*c[:, np.newaxis]
10000 loops, best of 3: 176 us per loop

%timeit b*c
10 loops, best of 3: 16.5 ms per loop

【讨论】:

  • 谢谢!这希望现在可以解决问题。我在newaxis 上阅读了一些内容,虽然仍然很模糊,但它适用于我现在能想到的所有情况。在这个阶段,我根本不考虑性能,但两种方法之间的性能差异是惊人的。再次感谢!
猜你喜欢
  • 1970-01-01
  • 2021-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多