有没有更有效的方法来“扩展”numpy数组?

n7taea2i  于 2023-03-23  发布在  其他
关注(0)|答案(2)|浏览(326)

一个算法要求我在一个方阵中添加一个额外的变量,这会导致在矩阵中添加一行和一列。我可以使用np.insert方法,如下所示,但想知道是否有更好的方法来对已经存在的分配数组执行此操作?
我试着玩了一个蒙面写,但没有成功:

import numpy as np

m1 = np.array([[1,3,4,5],
               [11,13,14,15],
               [16,18,19,20],
               [21,23,24,25]
              ])

row_1 = np.array([6,8,9,10])
col_1 = np.array([2,7,12,17,22])

m2 = np.insert(m1, 1, row_1, axis=0)
m2 = np.insert(m2, 1, col_1, axis=1)
print(f'{m2=}')

# create a mask to copy data from m1
m1_mask = np.ones(tuple(np.array(m1.shape) + 1), dtype=int)
expanded_m1 = np.zeros(tuple(np.array(m1.shape) + 1))
m1_mask[:,1] = 0
m1_mask[1, :] = 0
print(m1_mask)
# only write the indices where there are 1's from the original m1 data
expanded_m1[m1_mask] = m1
print(expanded_m1)
6za6bjd0

6za6bjd01#

您的expanded_m1[m1_mask] = m1失败,因为LHS引用(5, 5, 5)数组。

>>> expanded_m1[m1_mask].shape
(5, 5, 5)

如果你把m1_mask作为一个布尔型数组,并在其定义中加上dtype=bool,它就变成了一个掩码。在设置了m1_mask[:, 1] = 0m1_mask[1, :] = 0之后,我们得到了m1_mask

[[ True False  True  True  True]
 [False False False False False]
 [ True False  True  True  True]
 [ True False  True  True  True]
 [ True False  True  True  True]]

然后,expanded_m1[m1_mask]返回元素的 vector,因为它无法知道结果实际上是一个非不规则数组。

>>> expanded_m1[m1_mask].shape
(16,)

>>> m1_mask.sum()
16

如果您还展平m1,则可以设置这些元素:

>>> expanded_m1[m1_mask] = m1.flatten()
>>> print(expanded_m1)
[[ 1.  0.  3.  4.  5.]
 [ 0.  0.  0.  0.  0.]
 [11.  0. 13. 14. 15.]
 [16.  0. 18. 19. 20.]
 [21.  0. 23. 24. 25.]]

然后,您可以设置新的行和列。需要一些技巧,因为row只有四个元素,但这很容易处理:

row_mask = m1_mask[0]
expanded_m1[1, row_mask] = row_1
expanded_m1[:, 1] = col_1

然而,这并没有明显更快。考虑下面的图表,该图表显示了np.insert方法与掩码方法以及显式设置新数组的每个“片段”(如Kelly shows in their answer)的性能比较。手动设置所有内容而不是创建掩码会快2倍。

def insert(arr, row_1, col_1):
    return np.insert(np.insert(arr, 1, row_1, axis=0), 1, col_1, axis=1)

def alloc_then_assign(arr, row_1, col_1):
    m1_mask = np.ones(np.array(arr.shape) + 1, dtype=bool)
    expanded_m1 = np.zeros_like(m1_mask, dtype=arr.dtype)
    m1_mask[:,1] = 0
    m1_mask[1, :] = 0
    expanded_m1[m1_mask] = arr.flatten()
    row_mask = m1_mask[0]
    expanded_m1[1, row_mask] = row_1
    expanded_m1[:, 1] = col_1
    return expanded_m1

svmlkihl

svmlkihl2#

另一个:

def piecewise(m1, row_1, col_1):
    m3 = np.empty(np.array(m1.shape) + 1, dtype=m1.dtype)
    m3[0, 0] = m1[0, 0]
    m3[0, 2:] = m1[0, 1:]
    m3[2:, 0] = m1[1:, 0]
    m3[2:, 2:] = m1[1:, 1:]
    m3[1, 0] = row_1[0]
    m3[1, 2:] = row_1[1:]
    m3[:, 1] = col_1
    return m3

相关问题