[a b c ]
[ a b c ]
[ a b c ]
[ a b c ]
您好
对于我的经济学课程,我们假设要创建一个看起来像这样的数组。问题是我是经济学家而不是程序员。我们在python中使用numpy。我们的教授说大学不是为现实世界做准备,而是希望我们学习编程(这是一件好事)。我们不允许使用任何软件包,并且必须提供原始代码。有没有人知道如何制作这个矩阵。我花了几个小时尝试代码和浏览互联网寻求帮助,但都没有成功。
答案 0 :(得分:5)
这种矩阵称为Toeplitz matrix或恒定对角矩阵。了解这一点会导致您scipy.linalg.toeplitz
:
import scipy.linalg
scipy.linalg.toeplitz([1, 0, 0, 0], [1, 2, 3, 0, 0, 0])
=>
array([[1, 2, 3, 0, 0, 0],
[0, 1, 2, 3, 0, 0],
[0, 0, 1, 2, 3, 0],
[0, 0, 0, 1, 2, 3]])
答案 1 :(得分:4)
以下方法一次填充一个对角线:
import numpy as np
x = np.zeros((4, 6), dtype=np.int)
for i, v in enumerate((6,7,8)):
np.fill_diagonal(x[:,i:], v)
array([[6, 7, 8, 0, 0, 0],
[0, 6, 7, 8, 0, 0],
[0, 0, 6, 7, 8, 0],
[0, 0, 0, 6, 7, 8]])
或者你可以做一个班轮:
x = [6,7,8,0,0,0]
y = np.vstack([np.roll(x,i) for i in range(4)])
就个人而言,我更喜欢第一个,因为它更容易理解,并且可能更快,因为它不构建所有临时1D阵列。
修改强>
由于对效率的讨论已经出现,因此进行测试可能是值得的。我还把chthonicdaemon建议的toeplitz
方法包括在内的时间(虽然我亲自解释了这个问题,因为它使用了一个包而不是使用原始代码 - 但速度也不是原始问题的重点。任一)。
import numpy as np
import timeit
import scipy.linalg as sl
def a(m, n):
x = np.zeros((m, m), dtype=np.int)
for i, v in enumerate((6,7,8)):
np.fill_diagonal(x[:,i:], v)
def b(m, n):
x = np.zeros((n,))
x[:3] = vals
y = np.vstack([np.roll(x,i) for i in range(m)])
def c(m, n):
x = np.zeros((n,))
x[:3] = vals
y = np.zeros((m,))
y[0] = vals[0]
r = sl.toeplitz(y, x)
return r
m, n = 4, 6
print timeit.timeit("a(m,n)", "from __main__ import np, a, b, m, n", number=1000)
print timeit.timeit("b(m,n)", "from __main__ import np, a, b, m, n", number=1000)
print timeit.timeit("c(m,n)", "from __main__ import np, c, sl, m, n", number=1000)
m, n = 1000, 1006
print timeit.timeit("a(m,n)", "from __main__ import np, a, b, m, n", number=1000)
print timeit.timeit("b(m,n)", "from __main__ import np, a, b, m, n", number=1000)
print timeit.timeit("c(m,n)", "from __main__ import np, c, sl, m, n", number=100)
# which gives:
0.03525209 # fill_diagonal
0.07554483 # vstack
0.07058787 # toeplitz
0.18803215 # fill_diagonal
2.58780789 # vstack
1.57608604 # toeplitz
因此,对于小型阵列,第一种方法的速度要快2-3倍,对于较大的阵列,速度要快10-20倍。
答案 2 :(得分:1)
的内容
import numpy as np
def createArray(theinput,rotations) :
l = [theinput]
for i in range(1,rotations) :
l.append(l[i-1][:])
l[i].insert(0,l[i].pop())
return np.array(l)
print(createArray([1,2,3,0,0,0],4))
"""
[[1 2 3 0 0 0]
[0 1 2 3 0 0]
[0 0 1 2 3 0]
[0 0 0 1 2 3]]
"""
答案 3 :(得分:1)
这是一个简化的三对角矩阵。所以它基本上是this question
def tridiag(a, b, c, k1=-1, k2=0, k3=1):
return np.diag(a, k1) + np.diag(b, k2) + np.diag(c, k3)
a = [1, 1]; b = [2, 2, 2]; c = [3, 3]
A = tridiag(a, b, c)
print(A)
结果:
array([[2, 3, 0],
[1, 2, 3],
[0, 1, 2]])
答案 4 :(得分:0)
如果你关心效率,很难打败这个:
import numpy as np
def create_matrix(diags, n):
diags = np.asarray(diags)
m = np.zeros((n,n+len(diags)-1), diags.dtype)
s = m.strides
v = np.lib.index_tricks.as_strided(
m,
(len(diags),n),
(s[1],sum(s)))
v[:] = diags[:,None]
return m
print create_matrix(['a','b','c'], 8)
可能会略微超过你的头脑,但那又是一个很好的灵感;)
甚至更好:具有O(n)存储和运行时要求的解决方案,而不是迄今为止发布的所有其他解决方案,即O(n ^ 2)
import numpy as np
def create_matrix(diags, n):
diags = np.asarray(diags)
b = np.zeros(len(diags)+n*2, diags.dtype)
b[n:][:len(diags)] = diags
s = b.strides[0]
v = np.lib.index_tricks.as_strided(
b[n:],
(n,n+len(diags)-1),
(-s,s))
return v
print create_matrix(np.arange(1,4), 8)
答案 5 :(得分:0)
这是一个老问题,但是一些新输入总是有用的。
我使用list comprehension在python中创建三对角矩阵。
说一个围绕“-2”对称并且两边都有“1”的矩阵:
-2 1 0
Tsym(3) => 1 -2 1
0 1 -2
可以使用以下“one liner”创建:
Tsym = lambda n: [ [ 1 if (i+1==j or i-1==j) else -2 if j==i else 0 for i in xrange(n) ] for j in xrange(n)] # Symmetric tridiagonal matrix (1,-2,1)
一个不同的案例(其他几个回答的人已经完全解决了):
1 2 3 0 0 0
Tgen(4,6) => 0 1 2 3 0 0
0 0 1 2 3 0
0 0 0 1 2 3
可以使用下面显示的单个衬垫制作。
Tgen = lambda n,m: [ [ 1 if i==j else 2 if i==j+1 else 3 if i==j+2 else 0 for i in xrange(m) ] for j in xrange(n)] # General tridiagonal matrix (1,2,3)
随意修改以满足您的特定需求。这些矩阵在建模物理系统时非常常见,我希望这对某人(除了我)有用。
答案 6 :(得分:0)
您好,因为您的教授要求您不要导入任何外部包,而大多数答案都使用numpy或scipy。 你最好只使用python List来创建2D数组(复合列表),然后用你想要的项目填充它的对角线,找到下面的代码
def create_matrix(rows = 4, cols = 6):
mat = [[0 for col in range(cols)] for row in range(rows)] # create a mtrix filled with zeros of size(4,6)
for row in range(len(mat)): # gives number of lists in the main list,
for col in range(len(mat[0])): # gives number of items in sub-list 0, but all sublists have the same length
if row == col:
mat[row][col] = "a"
if col == row+1:
mat[row][col] = "b"
if col == row+2:
mat[row][col] = "c"
return mat
create_matrix(4, 6)
[[' a',' b',' c',0,0,0],
[0,' a',' b',' c',0,0],
[0,0,' a',' b',' c',0],
[0,0,0,' a',' b',' c']]
答案 7 :(得分:0)
创建波段矩阵
在 wiki 中查看它的定义: https://en.wikipedia.org/wiki/Band_matrix
您可以使用此函数创建带状矩阵,例如带 offset=1
的对角矩阵或带 offset=1
的 三对角 矩阵(您正在询问的) }} 或带有 offset=2
def band(size=10, ones=False, low=0, high=100, offset=2):
shape = (size, size)
n_matrix = np.random.randint(low, high, shape) if not ones else np.ones(shape,dtype=int)
n_matrix = np.triu(n_matrix, -1*offset)
n_matrix = np.tril(n_matrix, offset)
return n_matrix
在你的情况下,你应该使用这个
rand_tridiagonal = band(size=6,offset=1)
print(rand_tridiagonal)