首页 > 解决方案 > 将 numpy 数组或二维数组乘以向量的常用方法

问题描述

我想得到 ax = as_x-aseg_3d*aline_a 的结果

其中 as_x 和 aline_a 是 numpy 向量,而 aseg_3d 是数组数组。as_x.shape 和 aline_a 形状是 (S,),而 aseg_3d 形状也显示为 (S,),因为它应该是数组数组。结果 ax 也是一个与 aseg_3d 形状相同的数组。

问题是, aseg_3d 是一个数组数组,因为里面的数组有不同的长度。但是,有时它们不会,并且 aseg_3d 只是一个 2D 数组。然后上面的乘法在 ValueError 上失败:操作数无法与形状 (S,N) 一起广播。

我可以通过这样做来解决它: ax = as_x[:,None]-aseg_3d*aline_a[:,None]

但是当我有一个数组数组时,这对于前一种情况的工作方式不同。

有没有办法让它在两种情况下都起作用:数组数组和二维数组?

或者,即使所有内部数组都具有相同的长度,也可能有一种方法可以保留数组 dtype="object" 的 numpy 数组?

顺便提一句。我试图用列表推导进行上述乘法运算,这总是有效的,但速度要慢得多。

谢谢大家的建议!

标签: pythonarraysnumpy

解决方案


在任何一种情况下都有效的表达式:

您可以使用转置。简单的情况(只是乘法):

(vector * vec_of_vecs_or_2D.T).T

完整的操作示例:

(vector1 - vector2 * vec_of_vecs_or_2D.T).T

例子:

>>> v = np.array([3, 5])
>>> A = np.array((*map(np.array,[[1,2],[1,2,3]]),))
>>> B = np.array([[1,2,4],[1,2,3]])
>>> 
>>> v
array([3, 5])
>>> A
array([array([1, 2]), array([1, 2, 3])], dtype=object)
>>> B
array([[1, 2, 4],
       [1, 2, 3]])
>>> 
>>> (v*B.T).T
array([[ 3,  6, 12],
       [ 5, 10, 15]])
>>> (v*A.T).T
array([array([3, 6]), array([ 5, 10, 15])], dtype=object)

这个怎么运作:

如果vec_of_vecs_or_2D是对象 dtype 的 1D,则转置什么也不做。

如果vec_of_vecs_or_2D是真正的 2D,则转置将轴匹配移动vector到末尾,因此vector正确广播,然后再返回。

为什么便宜:

请注意,转置numpy是惰性的。它实际上并没有移动任何数据,它只是“交换轴标签”。

例如,1000x1000在我的笔记本电脑上对数组进行转置大约需要 200 ns:

>>> a = np.arange(1_000_000).reshape(1000, 1000)
>>> timeit(lambda: a.T)
0.22008929261937737

或者,在任何情况下强制数组数组:

例子

>>> L1 = [np.arange(i, 2*i+2) for i in range(3)]
>>> L2 = [np.arange(i, i+3) for i in range(3)]
>>> L1
[array([0, 1]), array([1, 2, 3]), array([2, 3, 4, 5])]
>>> L2
[array([0, 1, 2]), array([1, 2, 3]), array([2, 3, 4])]

方法1(丑陋但简单):

>>> A1 = np.array([*L1, None])[:-1]
>>> A2 = np.array([*L2, None])[:-1]
>>> A1
array([array([0, 1]), array([1, 2, 3]), array([2, 3, 4, 5])], dtype=object)
>>> A2
array([array([0, 1, 2]), array([1, 2, 3]), array([2, 3, 4])], dtype=object)

方法2:(不那么难看但复杂)

>>> A1 = np.frompyfunc(L1.__getitem__, 1, 1)(range(len(L1)))
>>> A2 = np.frompyfunc(L2.__getitem__, 1, 1)(range(len(L2)))
>>> A1
array([array([0, 1]), array([1, 2, 3]), array([2, 3, 4, 5])], dtype=object)
>>> A2
array([array([0, 1, 2]), array([1, 2, 3]), array([2, 3, 4])], dtype=object)

推荐阅读