考虑数组a
,在这个例子中,它有5行6列。
每一行都包含0到5的值。a
的30个元素使用以下规则组成15对:如果行的列p保存值q,则该行的列q保存值p。为了避免配对的重复,我们只考虑p > q的配对。
a = np.array([[1, 0, 3, 2, 5, 4],
[2, 4, 0, 5, 1, 3],
[3, 5, 4, 0, 2, 1],
[4, 3, 5, 1, 0, 2],
[5, 2, 1, 4, 3, 0]])
以下是15个配对中的一些,由列索引命名:
在行0中,配对(0,1)
保存值(1,0)
,配对(2,3)
保存值(3,2)
,配对(4,5)
保存值(5,4)
。
等等
在行4中,配对(0,5)
保存值(5,0)
,配对(1,2)
保存值(2,1)
,配对(3,4)
保存值(4,3)
。
现在,考虑数组m
。
m = np.array([[0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4],
[1, 2, 3, 4, 5, 2, 3, 4, 5, 3, 4, 5, 4, 5, 5],
[6, 4,-2, 5, 0,-1, 1, 4,-7,-8,-7, 3,-4, 1, 0],
[3,-8, 1, 2, 1, 3, 1, 6, 5, 5, 0, 2, 3, 1, 0]])
m
的前两行显示了15对(0,1), (0,2), ... (0,5), (1,2), ... (3,4), (3,5), (4,5)
。m
的最后两行显示的值,对于每个配对,必须添加到a
的相应元素中。
因此,对于a
配对(0, 1)
,我们将(6, 3)
添加到现有值(1, 0)
以获得值(7, 3)
对于a
对(0, 2)
,我们将(4,-8)
添加到现有值(2, 0)
以获得值(6,-8)
。
最后的结果看起来像这样:
c = np.array([[7, 3,-5, 7, 5, 4],
[6, 8,-8, 6, 7, 4],
[1,-2,-3, 1, 2, 6],
[9, 4, 8, 2, 2, 4],
[5, 1, 4, 0, 6, 1]])
问题:如何使用m
中的值修改a
中的值以生成c
?
1条答案
按热度按时间fruv7luv1#
我很确定有一个更简单的方法,因为我的解决方案是O(nmp),(n×m是矩阵
a
的大小,p
是矩阵M
中的列数。当它应该有可能有一个O(np)的解决方案时(对于矩阵
m
中的每一列,我们访问矩阵a
的匹配列,并搜索行)。但至少它是“矢量化的”;它不使用python
for
循环创建三维布尔掩码。轴0表示
m
的每一列。轴1和2是a
的行和列。如果
m[1,k]
等于a[i,j]
且j
(又名col[k,i,j]
)等于m[0,k]
,则该掩码中的位置k,i,j
为True。因此,掩码中位置
k,i,j
处的True
意味着在a
的位置i
,j
处,存在等于m[0,k]
的值我们需要将
m[2,k]
添加到a
中的[i,j]
位置。并在同一row
i
,但列m[1,k]
添加m[3,k]
。所以剩下的
当然,如果您希望保持原始
a
的完整性,则需要在此之前创建a
的副本所以匹配函数
非矢量化版本
为了强调我最初的观点(从复杂性的Angular 来看,它不是最佳的),下面是如何使用
for
循环来完成的复杂性低一个数量级。不过,它是3倍慢与您的例子。它可能会随着更大的例子而改变
编辑:双向
实际上,我只需要编写
for loop
版本就可以实现这个版本也可以“矢量化”。所以我们可以鱼与熊掌兼得。也就是说,有一个O(np)版本,不使用for循环即使在你的小例子中,它也比其他两个方法快。在更长的时间里应该会赢得更多。
a[:, m[0,:]]
是一个5×15矩阵,其列是m
的第一行中给定的列(即一个5×15矩阵,其元素i,j
是矩阵a
的元素i,m[0,j]
)所以
(a[:, m[0,:]]==m[1,:])
是一个5×15的布尔矩阵,其在i,j
位置的元素为真当且仅当矩阵a
的元素i,m[0,j]等于m
的第1行第j列的值。换句话说,我不知道。换句话说,在每个j=0到14列中,你在行位置有True
,在列m[0,j]
中你可以找到m[1,j]
中的值。例如,这个布尔矩阵的第7列在第1行(第二行)包含
True
,因为在矩阵a
的第1列(1是我们在m
的第7列第1行找到的)中,你在第1行找到了4(m
的第7列第2行)。因此,该矩阵具有
m
那么多列。每列包含一个,而且只有一个True
。匹配行,其中,在矩阵a
中,我可以在m
的第1行中指示的列中找到m
的第2行中的值。通过转置这个布尔矩阵,我得到一个15×5的布尔矩阵。由于
np.where
的工作顺序,这确保了我将获得15的位置。因此
np.where((a[:, m[0,:]]==m[1,:]).T)[1]
是我需要知道的15行。(...[0]
只是数字0到14)对于m
的每一列,这给予我a
的行号,我可以在m
的第一行指示的列中找到m
的第二行中的值。所以,
a[row]
是15,我需要改变的15行,对于m
的每15列。a[row, m[0]]
是15个值,在那些行、列m[0]
的a中找到。我需要把在m[2]
中找到的15个值加到这15个值上。同样,a[row, m[1]]
是匹配列中相同行的15个值。我需要将在m
的第4行中找到的15个值添加到其中。