Ted Desmond
Ted Desmond

Reputation: 57

Converting a list of lists to an array in Python

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

Answers (2)

B. M.
B. M.

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

Simon
Simon

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

Related Questions