将2D数组插入(更大的)2D数组的最快方法

4

假设有两个二维数组,ab

import numpy as np
a = np.random.rand(3, 4)
b = np.random.zeros(8, 8)

而且b在两个轴上始终大于a

(编辑:b初始化为零数组,以反映所有未被a占用的元素将保持为零的事实。)

问题。"插入"ab的最快或最Pythonic方法是什么?

到目前为止,我尝试了两件事:

  1. 使用np.pada转换为形状为(8,8)的数组
  2. 循环遍历a中的每一行,并将其放置在b中的相应行中

我没有尝试过使用双重嵌套循环迭代a的每个元素,因为我认为这不利于性能。

动机。每个数组a都是一个小字符,我想将每个字符馈送到接受形状为(8,8)的平坦数组的神经网络中,即形状为(64,)的数组。(我认为我不能简单地将a压缩为一个维度并用零填充它,因为然后它的二维结构会变形,所以我必须首先将其"重新塑造"成(8,8),对吗?)有几百万个字符。


在最后一段中,您提到了用零填充,但在您提供的示例中,b 具有随机值。那么您需要什么:从 b 中填充 a 的值,还是用零填充?填充在右侧和底部吗? - trincot
什么是“插入”? - TuanDT
4
为什么不使用 b[?:?, ?:?] = a?这将切片匹配 b 的块,作为放置 a 的位置。 - hpaulj
@trincot 错了,b 应该是 np.zeros。另外,最好填充的位置是居中的,但左上角也可以。 - étale-cohomology
@Allen其他元素都用0填充。 - étale-cohomology
显示剩余2条评论
3个回答

9

关于:

b[:a.shape[0],:a.shape[1]] = a

请注意,我假设将a放在b的开始位置,但您可以稍微调整一下,将a放在任何地方:

a0,a1=1,1
b[a0:a0+a.shape[0],a1:a1+a.shape[1]] = a

2

更一般地,如果您创建一个切片元组(这适用于任意维度),则可以确定要插入数组的位置:

>>> a = np.random.random((5,5))
>>> b = np.ones((3,3))

>>> edge_coordinate = (0,0)
>>> slicer = tuple(slice(edge, edge+i) for edge, i in zip(edge_coordinate, b.shape))
>>> a[slicer] = b
>>> a
array([[ 1.        ,  1.        ,  1.        ,  0.14206495,  0.36385016],
       [ 1.        ,  1.        ,  1.        ,  0.08861402,  0.7888898 ],
       [ 1.        ,  1.        ,  1.        ,  0.1975496 ,  0.13345192],
       [ 0.550487  ,  0.22471952,  0.47050879,  0.04669643,  0.13480528],
       [ 0.25139511,  0.06499812,  0.42247189,  0.05840351,  0.74735495]])

通过改变edge_coordinate,您可以改变位置:

>>> a = np.random.random((5,5))
>>> b = np.ones((3,3))

>>> edge_coordinates = (1,1)  # changed
>>> slicer = tuple(slice(edge, edge+i) for edge, i in zip(edge_coordinates, b.shape))
>>> a[slicer] = b
>>> a
array([[ 0.21385714,  0.68789872,  0.3915475 ,  0.67342566,  0.05642307],
       [ 0.19778658,  1.        ,  1.        ,  1.        ,  0.70717406],
       [ 0.73678924,  1.        ,  1.        ,  1.        ,  0.90285997],
       [ 0.39709332,  1.        ,  1.        ,  1.        ,  0.96959814],
       [ 0.89627195,  0.21295355,  0.72598992,  0.80749348,  0.76660287]])

理想情况下,如果您经常使用它,可以将其制作成一个函数。

但这不是花哨的索引吗?一般来说,它会创建一个新的数组。我只想获取一个之前分配的数组的“视图”,然后对其进行写入。 - étale-cohomology
1
@étale-cohomology 不,切片元组是常规索引并返回视图。 - MSeifert

0

我认为最好的方法是使用填充。

如果你想把一个元素放在左上角:

np.pad(a,((0,5),(0,4)),'constant') 

如果你想讓一個元素置中:

np.pad(a,((2,3),(2,2)),'constant')

1
但这是最快和最自然的方式吗?这样做会不会创建一个新的数组(我宁愿不这样做)? - étale-cohomology

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接