如何将一个numpy数组中的行与另一个数组中的多列相乘?

如何将一个numpy数组中的行与另一个数组中的多列相乘?,numpy,Numpy,我有一个棘手的问题 我有一个2D值数组 vals=np.array([[1.0, 2.0, 3.0],[4.0, 5.0, 6.0],[7.0, 8.0, 9.0]], np.float32) 和二维比例因子数组 factors=np.array([[1.0, 4.0], [2.0, 5.0], [3.0, 6.0]]) 我想将VAL中的每一行与因子中的每一行相乘,得到一个“scaled_vals”数组,如下所示 注意:此输出已从我的原始帖子中更正-我对这一错误表示歉意 [[ 1. 2.

我有一个棘手的问题

我有一个2D值数组

vals=np.array([[1.0, 2.0, 3.0],[4.0, 5.0, 6.0],[7.0, 8.0, 9.0]], np.float32)
和二维比例因子数组

factors=np.array([[1.0, 4.0], [2.0, 5.0], [3.0, 6.0]])
我想将VAL中的每一行与因子中的每一行相乘,得到一个“scaled_vals”数组,如下所示 注意:此输出已从我的原始帖子中更正-我对这一错误表示歉意

[[ 1.  2.  3.]
 [ 8. 10. 12.]
 [21. 24. 27.]]
[[ 4.  8. 12.]
 [20. 25. 30.]
 [42. 48. 54.]]
我只是用两列数据显示因子,但实际上它是“n”

任何帮助都将受到感激

道格

===

从评论中复制:

for step in range(2): 
    scaled_vals = np.multiply(vals, factors[0:,step:step+1])

我唯一能理解输入和输出的方法是,将每行VAL与所有因子的相应索引相乘,但需要匹配因子和VAL的维度

import numpy as np

vals=np.array([[1.0, 2.0, 3.0],[4.0, 5.0, 6.0],[7.0, 8.0, 9.0]], np.float32) # shape = mxn

print(vals.shape)

factors=np.array([[1.0, 4.0], [2.0, 5.0], [3.0, 6.0]]) # shape = nxk increasing dim to match with vals.shape

m = vals.shape[0]
n = vals.shape[1]
k = factors.shape[1]

print(factors.shape)



result = np.array([np.array([vals[j]*np.repeat(factors[:,i], n).reshape(n,n) for i in range(k)]) for j in range(m)])

print(result[0])


播放
广播

vals[:, None, None, :] * factors.T[None, :, :, None]
输出:

array([[[[ 1.,  2.,  3.],
         [ 2.,  4.,  6.],
         [ 3.,  6.,  9.]],

        [[ 4.,  8., 12.],
         [ 5., 10., 15.],
         [ 6., 12., 18.]]],


       [[[ 4.,  5.,  6.],
         [ 8., 10., 12.],
         [12., 15., 18.]],

        [[16., 20., 24.],
         [20., 25., 30.],
         [24., 30., 36.]]],


       [[[ 7.,  8.,  9.],
         [14., 16., 18.],
         [21., 24., 27.]],

        [[28., 32., 36.],
         [35., 40., 45.],
         [42., 48., 54.]]]])
您显示的(2,3,3)块可以通过以下方式生成:

In [267]: vals[0,:]*factors.T[:,:,None]                                                                
Out[267]: 
array([[[ 1.,  2.,  3.],
        [ 2.,  4.,  6.],
        [ 3.,  6.,  9.]],

       [[ 4.,  8., 12.],
        [ 5., 10., 15.],
        [ 6., 12., 18.]]])
但评论循环是

In [268]: for step in range(2):  
     ...:     print(np.multiply(vals, factors[0:,step:step+1])) 
     ...:                                                                                              
[[ 1.  2.  3.]
 [ 8. 10. 12.]
 [21. 24. 27.]]
[[ 4.  8. 12.]
 [20. 25. 30.]
 [42. 48. 54.]]
In [269]: vals*factors.T[:,:,None]                                                                     
Out[269]: 
array([[[ 1.,  2.,  3.],
        [ 8., 10., 12.],
        [21., 24., 27.]],

       [[ 4.,  8., 12.],
        [20., 25., 30.],
        [42., 48., 54.]]])

您可以使用
einsum
一条直线(不带循环)将索引乘以所需的任何形状:

output = np.einsum('ij,kl->ilkj',vals,factors)
这将
[i,j]
VAL
乘以
[k,l]
因子
并将其置于输出中的
[i,l,k,j]
。注@Quan Hoang的答案(向上投票)同样没有循环。然而,我认为这更具可读性,您可以将其扩展到您想要的任何其他组合

输出:

[[[[ 1.  2.  3.]
   [ 2.  4.  6.]
   [ 3.  6.  9.]]

  [[ 4.  8. 12.]
   [ 5. 10. 15.]
   [ 6. 12. 18.]]]


 [[[ 4.  5.  6.]
   [ 8. 10. 12.]
   [12. 15. 18.]]

  [[16. 20. 24.]
   [20. 25. 30.]
   [24. 30. 36.]]]


 [[[ 7.  8.  9.]
   [14. 16. 18.]
   [21. 24. 27.]]

  [[28. 32. 36.]
   [35. 40. 45.]
   [42. 48. 54.]]]]
[[[ 1.  2.  3.]
  [ 8. 10. 12.]
  [21. 24. 27.]]

 [[ 4.  8. 12.]
  [20. 25. 30.]
  [42. 48. 54.]]]
更新:根据评论中提到的新乘法,解决方案为:

output = np.einsum('ij,ik->kij',vals,factors)
这将VAL中的
[i,j]
乘以因子中的
[i,k]
,并将其置于输出中的
[k,i,j]

输出:

[[[[ 1.  2.  3.]
   [ 2.  4.  6.]
   [ 3.  6.  9.]]

  [[ 4.  8. 12.]
   [ 5. 10. 15.]
   [ 6. 12. 18.]]]


 [[[ 4.  5.  6.]
   [ 8. 10. 12.]
   [12. 15. 18.]]

  [[16. 20. 24.]
   [20. 25. 30.]
   [24. 30. 36.]]]


 [[[ 7.  8.  9.]
   [14. 16. 18.]
   [21. 24. 27.]]

  [[28. 32. 36.]
   [35. 40. 45.]
   [42. 48. 54.]]]]
[[[ 1.  2.  3.]
  [ 8. 10. 12.]
  [21. 24. 27.]]

 [[ 4.  8. 12.]
  [20. 25. 30.]
  [42. 48. 54.]]]

你能解释一下你是如何得到输出的吗?我无法理解乘法的任何组合。这只是输出的第一个元素吗?使用循环为范围(2)中的步长生成输出:scaled_vals=np.multiply(vals,factors[0:,step:step+1])现在我明白了。谢谢你的澄清。我有一个简单的一行解决方案,我张贴和索引,使它非常可读。所有-我完全搞砸了我的问题-我为浪费大家的时间道歉。我实际上试图实现的输出是,[[1.2.3.][8.10.12.][21.24.27.][[4.8.12.][20.25.30.][42.48.54.]]这就是循环实际产生的结果,正如HPaulj所指出的,您可以轻松地将我的帖子修改到您的设置中。我将在以后编辑此评论要求。我想应该是“ij,ik->kij'Ehsan”-谢谢你。我以前从未使用过einsum-非常有用!!!!我不确定是将这个答案标记为最佳解决方案还是来自Quang的解决方案,因为两者都给出了我需要的结果,并且几乎同时运行。我之所以选择这一款,是因为它的速度快了一点,并向我介绍了一种新的功能……我很高兴它对我有所帮助。einsum的强大功能超越了这个例子。知道它的力量,你会喜欢使用它。