Reputation: 57
I've been looking this up, but I couldn't find anything that helped. I'm having some trouble making an array of the size I want.
So far, I have created a list of lists with this code:
n=4
def matrixA(k):
A=[]
for m in range(0,k):
row=[]
#A.append([])
for n in range(0,k):
if (n==(m+1)) or (n==(m-1)):
row.append(-deltaX/(deltaX)**2)
if (n==m):
row.append(2*deltaX/(deltaX)**2)
else:
row.append(0)
A.append(row)
return A
pprint.pprint(matrixA(n))
print len(matrixA(n))
I get this output.
[[128.0, -64.0, 0, 0, 0],
[-64.0, 0, 128.0, -64.0, 0, 0],
[0, -64.0, 0, 128.0, -64.0, 0],
[0, 0, -64.0, 0, 128.0]]
4
Now, I want to make this an array of size (4,4). My problem is that when I do the following (converting the list to an array and trying to shape it):
A=numpy.array(matrixA(n))
print A
print "This is its shape:",A.shape
A.shape=(n,n)
I obtain:
[[128.0, -64.0, 0, 0, 0] [-64.0, 0, 128.0, -64.0, 0, 0]
[0, -64.0, 0, 128.0, -64.0, 0] [0, 0, -64.0, 0, 128.0]]
This is its shape: (4,)
And then an error:
ValueError: total size of new array must be unchanged
How am I supposed to get an array of size (4,4) from here then?
Upvotes: 1
Views: 1828
Reputation: 18668
Welcome in numpy world.
It seems that you want :
array([[ 128., -64., 0., 0.],
[ -64., 128., -64., 0.],
[ 0., -64., 128., -64.],
[ 0., 0., -64., 128.]])
It's difficult to think in terms of rows and cols indices when building list of lists. In numpy you shape first, then fill, which is often easier.
Step by step:
In [37]: from numpy import eye,diag,ones # some useful functions
In [38]: eye(4) # identity matrix
Out[38]:
array([[ 1., 0., 0., 0.],
[ 0., 1., 0., 0.],
[ 0., 0., 1., 0.],
[ 0., 0., 0., 1.]])
In [39]: eye(4)*128
Out[39]:
array([[ 128., 0., 0., 0.],
[ 0., 128., 0., 0.],
[ 0., 0., 128., 0.],
[ 0., 0., 0., 128.]])
In [40]: ones(3)
Out[40]: array([ 1., 1., 1.])
In [41]: diag(ones(3),1) # see help(diag)
Out[41]:
array([[ 0., 1., 0., 0.],
[ 0., 0., 1., 0.],
[ 0., 0., 0., 1.],
[ 0., 0., 0., 0.]])
In [42]: diag(ones(3),1).T # transpose
Out[42]:
array([[ 0., 0., 0., 0.],
[ 1., 0., 0., 0.],
[ 0., 1., 0., 0.],
[ 0., 0., 1., 0.]])
So what you want is something like :
def arrayA(n,deltaX):
A=eye(n) # id matrix of size n
B= diag(ones(n-1),1) # just ahead
return (2*A-B-B.T)*(deltaX/deltaX**2)
and run:
In [45]: arrayA(4,1/64)
Out[45]:
array([[ 128., -64., 0., 0.],
[ -64., 128., -64., 0.],
[ 0., -64., 128., -64.],
[ 0., 0., -64., 128.]])
And for big matrices, it is faster :
In [57]: %timeit arrayA(100,1/64)
1000 loops, best of 3: 326 µs per loop
In [58]: %timeit matrixA(100)
100 loops, best of 3: 14.9 ms per loop
Upvotes: 2
Reputation: 10158
Converting a nested list to an array is simple, and you were doing it correctly:
numpy.array(matrixA(n))
The reason it doesn't work is because the nested list you generate actually has an irregular number of "columns"
The problematic part is this as you're missing an elif
:
if (n==(m+1)) or (n==(m-1)):
row.append(-deltaX/(deltaX)**2)
if (n==m):
row.append(2*deltaX/(deltaX)**2)
Change your loop to:
for m in range(0,k-1):
row=[]
#A.append([])
for n in range(0,k-1):
if (n==(m+1)) or (n==(m-1)):
row.append(-deltaX/(deltaX)**2)
elif (n==m):
row.append(2*deltaX/(deltaX)**2)
else:
row.append(0)
A.append(row)
Upvotes: 0