如何从填充零的 3 维 numpy 数组创建 4 维 numpy 数组?

Posted

技术标签:

【中文标题】如何从填充零的 3 维 numpy 数组创建 4 维 numpy 数组?【英文标题】:How to create a 4 dimensional numpy array from a 3 dimensional numpy array filling with zeros? 【发布时间】:2021-03-05 12:45:23 【问题描述】:

问题

创建一个高维 NumPy 数组,在新维度上使用零

详情

分析最后一个维度,结果类似这样:

(不是实际代码,只是一个教学示例)

a.shape = (100,2,10) 
a[0,0,0]=1
a[0,0,1]=2  
...
a[0,0,9]=10

b.shape = (100,2,10,10)
b[0,0,0,:]=[0,0,0,0,0,0,0,0,0,1]
b[0,0,1,:]=[0,0,0,0,0,0,0,0,2,1] 
b[0,0,2,:]=[0,0,0,0,0,0,0,3,2,1]
...
b[0,0,2,:]=[10,9,8,7,6,5,4,3,2,1] 
    
a -> b 

目标是从a 转换为b。问题是它不仅填充了零,而且与原始数组有顺序组合。

更简单的问题以便更好地理解

另一种可视化方法是使用低维数组:

我们有这个:

a = [1,2]

我想要这个:

b = [[0,1],[2,1]]

使用 NumPy 数组并避免长 for 循环。

2d 到 3d 案例

我们有这个:

a = [[1,2,3],[4,5,6],[7,8,9]]

我想要这个:

b[0] = [[0,0,1],[0,2,1],[3,2,1]]
b[1] = [[0,0,4],[0,5,4],[6,5,4]]
b[2] = [[0,0,7],[0,8,7],[9,8,7]]

我觉得对于 4 维问题只需要一个 for 循环 10 次迭代就足够了。

【问题讨论】:

b 的最后两个轴是一个深蹲数组,您可以使用三角矩阵来实现您的结果。当您说a = [1, 2] 时,您的意思是您希望b 的每一行从a 的每个元素倒数到0,然后对于该行中的任何剩余元素保持0?那是1-2顺序吗?你能有a = [1, 3, 2]吗? 我需要保留序列。我可以拥有a=[1,3,2],但我们拥有b = [[0,0,1],[0,1,3],[1,3,2]]。我不知道如何处理三角矩阵。我试图添加和删除元素并添加到具有更多维度的新 np.zeros 数组中。 在第一个示例中,数字以相反的顺序出现,即对于 [1, 2, 3..., 10],您会得到 [1], [2, 1], [3, 2, 1] 等。但在您的第二个示例中,它们以正序出现,即 [1]、[1、2]、[1、2、3]。你要哪一个? 两者都适合我,但我更喜欢相反的顺序。我将编辑问题。谢谢。 你的例子只关心a[0,0]。您希望示例的前两个轴中的每个索引都发生类似的事情,还是只针对特定的索引? 【参考方案1】:

numpy的框架下试试这样的:

import numpy as np

# create transformation tensors
N = a.shape[-1]
sigma1 = np.zeros((N,N,N))
sigma2 = np.zeros((N,N,N))
E = np.ones((N,N))
for i in range(N):
   sigma1[...,i] = np.diag(np.diag(E,N-1-i),N-1-i)
   sigma2[N-1-i,N-1-i:,i] = 1

b1 = np.tensordot(a, sigma1, axes=([-1],[0]))
b2 = np.tensordot(a, sigma2, axes=([-1],[0]))

其中sigma1sigma2 是转换张量,您可以根据需要转换与a 的最后一个维度关联的数据(您在问题和 cmets 中提到的两个版本)。这里循环仅用于创建转换张量。

对于a = [[1,2,3],[1,2,3],[1,2,3]],第一个算法给出:

[[[0. 0. 1.] [0. 1. 2.] [1. 2. 3.]] [[0. 0. 4.] [0. 4. 5.] [4. 5. 6.]] [[0。 0. 7.] [0. 7. 8.] [7. 8. 9.]]]

最后一个算法给出:

[[[0. 0. 1.] [0. 2. 1.] [3. 2. 1.]] [[0. 0. 4.] [0. 5. 4.] [6. 5. 4.]] [[0. 0. 7.] [0. 8. 7.] [9. 8. 7.]]]

在使用numpy 时尽量避免使用列表和循环,因为它们会减慢执行速度。

【讨论】:

这适用于一维数组,但不适用于二维及更大的情况。例如,如果我有a = np.array([[1,2,3],[1,2,3],[1,2,3]]),我会期望结果数组b[0] = array([[[0., 0., 1.],[0., 1., 2.],[1., 2., 3.]]b[1] = array([[[0., 0., 1.],[0., 1., 2.],[1., 2., 3.]]。我测试了代码,结果是b[1] = array([[2., 3., 1.],[3., 1., 2.],[1., 2., 3.]]) 请精确您的算法。现在,您会期望b[0]==b[1] 不是b[0]==b[1] 只适用于a = [[1,2,3],[1,2,3],[1,2,3]]。对于a = [[1,2,3],[4,5,6],[7,8,9]]b[0] = [[0,0,1],[0,1,2],[1,2,3]]b[1] = [[0,0,4],[0,4,5],[4,5,6]]的情况。 再一次,如果我正确理解了您的算法,请在我的答案中尝试更正后的代码。我引入了张量来转换你的最后一个维度数据。 您是否在我的回答中使用张量积检查了当前版本的代码?这就是你需要的?【参考方案2】:

我能够解决问题,但可能有更有效的方法:

a = np.array([[1,2,3],[4,5,6],[7,8,9]]) #two  dim case

a = np.array([[[1,2,3],[4,5,6],[7,8,9]],[[1,2,3],[4,5,6],[7,8,9]],[[1,2,3],[4,5,6],[7,8,9]]])# three dim case

def increase_dim(arr):
    stack_list = []
    stack_list.append(arr)
    for i in range(1,arr.shape[-1]):
       stack_list.append(np.delete(np.delete(np.append(np.zeros(arr.shape),arr,axis=-1),np.s_[-i:],axis = len(arr.shape)-1),np.s_[:arr.shape[-1]-i],axis = -1))    
    return np.stack(stack_list,axis = -1)

b = increase_dim(b)

我希望这可以帮助理解问题。

【讨论】:

你为什么在这个解释中交换了ab

以上是关于如何从填充零的 3 维 numpy 数组创建 4 维 numpy 数组?的主要内容,如果未能解决你的问题,请参考以下文章

如何用另一个数组创建或填充一个 numpy 数组?

从概念上讲,numpy 中的 N 维数组是啥? [复制]

如何创建一个全部为 True 或全部为 False 的 numpy 数组?

NumPy学习(让数据处理变简单)

numpy数组中的向后计数

在 NumPy 数组中查找等于零的元素的索引