1

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?

3
  • 3
    Your lists have 5 or 6 elements, how do you plan to make it into a 4x4 array? Also, because of the different number of elements in the lists, numpy does not create a 2D array, but instead creates a 1D array of dtype=object filled with lists. Commented Apr 5, 2016 at 10:47
  • Wow, I can't believe I didn't notice that. Do you know why there are 5 or 6 rather than just 5 here? (Also I changed the range from k to k-1 since you pointed that out since I want it to be 4 rather than 5, thanks.) Commented Apr 5, 2016 at 10:53
  • 2
    I'm guessing the second if inside the loops was supposed to be elif. Currently you append to row twice sometimes in one iteration. Also, you're overwriting n, not sure if you want that or not. Commented Apr 5, 2016 at 10:58

2 Answers 2

2

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
Sign up to request clarification or add additional context in comments.

Comments

0

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)

2 Comments

I'm pretty sure the problematic part is the next line, which should be elif, not if.
yes, I was too eager with hitting the submit button ;)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.