如何将二维数组复制到第三维,N 次?

2025-03-04 08:24:00
admin
原创
103
摘要:问题描述:我想将 numpy 2D 数组复制到第三维。例如,给定 2D numpy 数组:import numpy as np arr = np.array([[1, 2], [1, 2]]) # arr.shape = (2, 2) 将其转换为在新维度上有 N 个这样的副本的 3D 矩阵。arr对 进行操...

问题描述:

我想将 numpy 2D 数组复制到第三维。例如,给定 2D numpy 数组:

import numpy as np

arr = np.array([[1, 2], [1, 2]])
# arr.shape = (2, 2)

将其转换为在新维度上有 N 个这样的副本的 3D 矩阵。arr对 进行操作N=3,输出应为:

new_arr[:,:,0]
# array([[1, 2], [1, 2]])

new_arr[:,:,1]
# array([[1, 2], [1, 2]])

new_arr[:,:,2]
# array([[1, 2], [1, 2]])

# new_arr.shape = (2, 2, 3)

解决方案 1:

可能最干净的方法是使用np.repeat

a = np.array([[1, 2], [1, 2]])
print(a.shape)
# (2,  2)

# indexing with np.newaxis inserts a new 3rd dimension, which we then repeat the
# array along, (you can achieve the same effect by indexing with None, see below)
b = np.repeat(a[:, :, np.newaxis], 3, axis=2)

print(b.shape)
# (2, 2, 3)

print(b[:, :, 0])
# [[1 2]
#  [1 2]]

print(b[:, :, 1])
# [[1 2]
#  [1 2]]

print(b[:, :, 2])
# [[1 2]
#  [1 2]]

话虽如此,你通常可以通过使用广播来避免重复数组。例如,假设我想添加一个(3,)向量:

c = np.array([1, 2, 3])

a。我可以在第三维中复制 3 次的内容,然后在第一维和第二维中a复制两次的内容,这样我的两个数组都是,然后计算它们的总和。但是,这样做更简单、更快捷:c`(2, 2, 3)`

d = a[..., None] + c[None, None, :]

这里,a[..., None]具有形状(2, 2, 1),并且c[None, None, :]具有形状(1, 1, 3)*。当我计算总和时,结果会沿着大小为 1 的维度“广播”出去,从而得到形状为的结果(2, 2, 3)

print(d.shape)
# (2,  2, 3)

print(d[..., 0])    # a + c[0]
# [[2 3]
#  [2 3]]

print(d[..., 1])    # a + c[1]
# [[3 4]
#  [3 4]]

print(d[..., 2])    # a + c[2]
# [[4 5]
#  [4 5]]

广播是一种非常强大的技术,因为它避免了在内存中创建输入数组的重复副本所产生的额外开销。


  • 尽管我为了清晰起见将它们包括None在内,但索引c实际上并不是必需的 - 您也可以这样做,即针对数组a[..., None] + c广播一个数组。这是因为如果其中一个数组的维度少于另一个数组,则只有两个数组的尾部维度需要兼容。举一个更复杂的例子:(2, 2, 1)`(3,)`

a = np.ones((6, 1, 4, 3, 1))  # 6 x 1 x 4 x 3 x 1
b = np.ones((5, 1, 3, 2))     #     5 x 1 x 3 x 2
result = a + b                # 6 x 5 x 4 x 3 x 2

解决方案 2:

另一种方法是使用numpy.dstack。假设您想重复矩阵a num_repeats次数:

import numpy as np
b = np.dstack([a]*num_repeats)

诀窍是将矩阵包装a成单个元素的列表,然后使用*运算符复制该列表中的元素num_repeats次。

例如,如果:

a = np.array([[1, 2], [1, 2]])
num_repeats = 5

[1 2; 1 2]这在第三维中重复了 5 次数组。验证方法(在 IPython 中):

In [110]: import numpy as np

In [111]: num_repeats = 5

In [112]: a = np.array([[1, 2], [1, 2]])

In [113]: b = np.dstack([a]*num_repeats)

In [114]: b[:,:,0]
Out[114]: 
array([[1, 2],
       [1, 2]])

In [115]: b[:,:,1]
Out[115]: 
array([[1, 2],
       [1, 2]])

In [116]: b[:,:,2]
Out[116]: 
array([[1, 2],
       [1, 2]])

In [117]: b[:,:,3]
Out[117]: 
array([[1, 2],
       [1, 2]])

In [118]: b[:,:,4]
Out[118]: 
array([[1, 2],
       [1, 2]])

In [119]: b.shape
Out[119]: (2, 2, 5)

最后我们可以看到矩阵的形状是2 x 2,第三维有 5 个切片。

解决方案 3:

使用视图并获取免费运行时!将通用n-dim数组扩展为n+1-dim

在NumPy1.10.0中引入后,我们可以利用它简单地在输入数组中numpy.broadcast_to生成视图。这样做的好处是没有额外的内存开销,并且几乎不需要运行时间。当数组很大并且我们可以使用视图时,这一点至关重要。此外,这适用于一般情况。3D`2D`n-dim

我会用这个词stack来代替copy,因为读者可能会将其与创建内存副本的数组复制混淆。

沿第一个轴堆叠

arr如果我们想沿第一个轴堆叠输入,np.broadcast_to创建3D视图的解决方案将是 -

np.broadcast_to(arr,(3,)+arr.shape) # N = 3 here

沿第三/最后一个轴堆叠

arr要沿第三轴堆叠输入,创建3D视图的解决方案是 -

np.broadcast_to(arr[...,None],arr.shape+(3,))

如果我们确实需要内存副本,我们总是可以.copy()在那里附加。因此,解决方案将是 -

np.broadcast_to(arr,(3,)+arr.shape).copy()
np.broadcast_to(arr[...,None],arr.shape+(3,)).copy()

以下是两种情况的堆叠方式,并显示了示例案例的形状信息 -

# Create a sample input array of shape (4,5)
In [55]: arr = np.random.rand(4,5)

# Stack along first axis
In [56]: np.broadcast_to(arr,(3,)+arr.shape).shape
Out[56]: (3, 4, 5)

# Stack along third axis
In [57]: np.broadcast_to(arr[...,None],arr.shape+(3,)).shape
Out[57]: (4, 5, 3)

相同的解决方案可用于将n-dim输入扩展到n+1-dim沿第一个和最后一个轴的视图输出。让我们探索一些更高维度的情况 -

3D输入情况:

In [58]: arr = np.random.rand(4,5,6)

# Stack along first axis
In [59]: np.broadcast_to(arr,(3,)+arr.shape).shape
Out[59]: (3, 4, 5, 6)

# Stack along last axis
In [60]: np.broadcast_to(arr[...,None],arr.shape+(3,)).shape
Out[60]: (4, 5, 6, 3)

4D输入情况:

In [61]: arr = np.random.rand(4,5,6,7)

# Stack along first axis
In [62]: np.broadcast_to(arr,(3,)+arr.shape).shape
Out[62]: (3, 4, 5, 6, 7)

# Stack along last axis
In [63]: np.broadcast_to(arr[...,None],arr.shape+(3,)).shape
Out[63]: (4, 5, 6, 7, 3)

等等。

时间安排

让我们使用一个大样本2D案例,获取时间并验证输出是否为view

# Sample input array
In [19]: arr = np.random.rand(1000,1000)

让我们证明所提出的解决方案确实是一种观点。我们将沿第一轴进行堆叠(沿第三轴堆叠的结果非常相似)-

In [22]: np.shares_memory(arr, np.broadcast_to(arr,(3,)+arr.shape))
Out[22]: True

让我们来看看它的计时效果,它实际上是免费的 -

In [20]: %timeit np.broadcast_to(arr,(3,)+arr.shape)
100000 loops, best of 3: 3.56 µs per loop

In [21]: %timeit np.broadcast_to(arr,(3000,)+arr.shape)
100000 loops, best of 3: 3.51 µs per loop

作为一个视图,N从增加到3不会3000改变时间,并且两者在时间单位上都可以忽略不计。因此,内存和性能都很高效!

解决方案 4:

现在也可以使用np.tile来实现,如下所示:

import numpy as np

a = np.array([[1,2],[1,2]])
b = np.tile(a,(3, 1,1))

b.shape
(3,2,2)

b
array([[[1, 2],
        [1, 2]],

       [[1, 2],
        [1, 2]],

       [[1, 2],
        [1, 2]]])

解决方案 5:

A=np.array([[1,2],[3,4]])
B=np.asarray([A]*N)

编辑@Mr.F,以保留维度顺序:

B=B.T

解决方案 6:

这是一个完全按照要求执行的广播示例。

a = np.array([[1, 2], [1, 2]])
a=a[:,:,None]
b=np.array([1]*5)[None,None,:]

然后b*a就是期望的结果,并且(b*a)[:,:,0]产生array([[1, 2],[1, 2]]),也就是原始的a,就像也是如此(b*a)[:,:,1],等等。

解决方案 7:

总结上面的解决方案:

a = np.arange(9).reshape(3,-1)
b = np.repeat(a[:, :, np.newaxis], 5, axis=2)
c = np.dstack([a]*5)
d = np.tile(a, [5,1,1])
e = np.array([a]*5)
f = np.repeat(a[np.newaxis, :, :], 5, axis=0) # np.repeat again
print('b='+ str(b.shape), b[:,:,-1].tolist())
print('c='+ str(c.shape),c[:,:,-1].tolist())
print('d='+ str(d.shape),d[-1,:,:].tolist())
print('e='+ str(e.shape),e[-1,:,:].tolist())
print('f='+ str(f.shape),f[-1,:,:].tolist())

b=(3, 3, 5) [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
c=(3, 3, 5) [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
d=(5, 3, 3) [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
e=(5, 3, 3) [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
f=(5, 3, 3) [[0, 1, 2], [3, 4, 5], [6, 7, 8]]

祝你好运

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   3868  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   2711  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Freshdesk、ClickUp、nTask、Hubstaff、Plutio、Productive、Targa、Bonsai、Wrike。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在项目管理过程中面临着诸多痛点,如任务分配不...
项目管理系统   44  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Monday、TeamGantt、Filestage、Chanty、Visor、Smartsheet、Productive、Quire、Planview。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多项目经理和团队在管理复杂项目时,常...
开源项目管理工具   42  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Smartsheet、GanttPRO、Backlog、Visor、ResourceGuru、Productive、Xebrio、Hive、Quire。在当今快节奏的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在选择项目管理工具时常常面临困惑:...
项目管理系统   44  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用