Python:调整现有数组大小并填充零

34

我认为我的问题应该非常简单,但是我在互联网上找不到任何帮助。我很新于Python,所以可能会错过一些非常明显的东西。

我有一个数组S,像这样[x x x](一维)。现在,我创建了一个对角矩阵sigma,使用np.diag(S) - 到目前为止,一切正常。现在,我想调整这个新的对角数组的大小,以便可以将其乘以我拥有的另一个数组。

import numpy as np
...
shape = np.shape((6, 6)) #This will be some pre-determined size
sigma = np.diag(S) #diagonalise the matrix - this works
my_sigma = sigma.resize(shape) #Resize the matrix and fill with zeros - returns "None" - why?

然而,当我打印my_sigma的内容时,我得到了"None"。有人能否指点我正确的方向,因为我无法想象这应该是如此复杂。

提前感谢任何帮助!

Casper

图形化:

我有这个:

[x x x]

我想要这个:

[x 0 0]
[0 x 0]
[0 0 x]
[0 0 0]
[0 0 0]
[0 0 0] - or some similar size, but the diagonal elements are important.

你是在定义 shape()、diag() 和 resize(),还是使用的库中已有的函数? - grieve
resize() 是来自于 numpy 库的函数,我应该在之前进行说明。 - hjweide
这是numpy,对吧?如果我理解正确,sigma里面有数据,但你想让sigma变大并用零填充新元素。是这样吗?如果你只需要一个新的零填充数组,可以使用numpy.zeros((6,6)) - gfortune
1
np.shape((6, 6)) 返回的形状是 (2,),可能不是您想要的 (6,6)。对 diag 矩阵进行重新整形对我来说没有意义。它里面大多数都是零...不确定您真正想要什么。 - Phil Cooper
我需要使用当前数据的sigma,但我还需要调整它的大小,以便可以将其与另一个矩阵相乘。因此,我只需要将sigma调整到适当的大小,用零填充剩余值正是我想要的。我正在进行奇异值分解,sigma是我的S矩阵,必须对其进行对角化并与我的MxM S矩阵相乘。 - hjweide
5个回答

61

在numpy 1.7.0版本中,有一个新的函数numpy.pad可以一行代码实现此操作。与其他答案类似,您可以使用np.diag构造对角矩阵进行填充。

在这个答案中使用的元组((0,N),(0,0))表示要填充的矩阵的“边缘”。

import numpy as np

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

N = A.size
B = np.pad(np.diag(A), ((0,N),(0,0)), mode='constant')

B现在等于:

[[1 0 0]
 [0 2 0]
 [0 0 3]
 [0 0 0]
 [0 0 0]
 [0 0 0]]

1
感谢您发布更新的答案。在我点赞之前,我们的答案打成了平局,但我的答案是在numpy 1.7之前的。不确定您是否会成为最佳答案,因为StackOverflow存在“先来先得”的偏见。很高兴看到新的信息... - Phil Cooper

25
sigma.resize()的返回值为None,因为它是原地操作。而另一方面,np.resize(sigma,shape)返回结果,但它用数组的重复填充而不是用零填充。此外,shape()函数会返回输入的形状。如果您只想预定义一个形状,请使用元组。
import numpy as np
...
shape = (6, 6) #This will be some pre-determined size
sigma = np.diag(S) #diagonalise the matrix - this works
sigma.resize(shape) #Resize the matrix and fill with zeros

然而,这将首先展平您的原始数组,然后重新构造为给定的形状,破坏了原始顺序。如果您只想使用零进行“填充”,而不是使用resize(),则可以直接索引生成的零矩阵。

# This assumes that you have a 2-dimensional array
zeros = np.zeros(shape, dtype=np.int32)
zeros[:sigma.shape[0], :sigma.shape[1]] = sigma

谢谢,这非常接近我需要的东西-但现在我的新矩阵失去了对角线性,即最初沿对角线的元素不再保持在那里。有什么办法可以解决这个问题吗? - hjweide
谢谢!这太完美了,感谢你的努力,voithos! - hjweide

5
我看到了编辑的内容...你需要先创建零矩阵,然后将一些数字移动到其中。 np.diag_indices_from 对您可能有用。
bigger_sigma = np.zeros(shape, dtype=sigma.dtype)
diag_ij = np.diag_indices_from(sigma)
bigger_sigma[diag_ij] = sigma[diag_ij] 

这个似乎也可以,谢谢!我很高兴看到这是一个相当棘手的过程,而不仅仅是我漏掉了什么东西。 - hjweide
我更喜欢这个。更易读,只添加所需内容。此外,使用 sigma.dtype 是一个好主意。 - voithos
我猜测问题的背景是一个矩形矩阵的SVD(full_matrices=True),并且进行重构A = USV'。在这种情况下,我更喜欢这种类型的解决方案。 - Patrick

3
这个解决方案可以与 resize 函数一起使用。
拿一个示例数组。
S= np.ones((3))
print (S)
# [ 1.  1.  1.]
d= np.diag(S) 
print(d)
"""
[[ 1.  0.  0.]
 [ 0.  1.  0.]
 [ 0.  0.  1.]]

"""

这个并不起作用,它只是添加了重复的值。
np.resize(d,(6,3))
"""
adds a repeating value
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.],
       [ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.]])
"""

这个 确实 有效。
d.resize((6,3),refcheck=False)
print(d)
"""
[[ 1.  0.  0.]
 [ 0.  1.  0.]
 [ 0.  0.  1.]
 [ 0.  0.  0.]
 [ 0.  0.  0.]
 [ 0.  0.  0.]]
"""

如果您更改第二个维度而不是第一个维度,则不会发生任何变化。 - mxdbld

0

另一个纯Python的解决方案是

a = [1, 2, 3]
b = []
for i in range(6):
    b.append((([0] * i) + a[i:i+1] + ([0] * (len(a) - 1 - i)))[:len(a)])

b 现在是

[[1, 0, 0], [0, 2, 0], [0, 0, 3], [0, 0, 0], [0, 0, 0], [0, 0, 0]]

我承认这是一个丑陋的解决方案。 然而,它展示了一些可以使用的list类型函数。


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