user1121588
user1121588

Reputation:

Method for generating row-column arrays with other arrays

I am attempting to utilize numpy to the best of its capabilities, but I am obviously missing some important link in the documentation due to my 'Noob-ness'.
What I want to do is create an array with a certain number of rows and columns and populate it with a sub array. The sub array is incremented by a pair of values as one traverses along the row. For subsequent rows, another pair of values is used to populate the columns. The best I have come up with is to use list comprehensions to generate the desired output. At this stage I can create an array which doesn't have the desired shape...I can deal with that in an awkward fashion, so all is not lost.

Here is what I have so far:

>>> import numpy as np
>>> np.set_printoptions(precision=4,threshold=20,edgeitems=3,linewidth=80)   # default print options
>>> sub = np.array([[1,2],[3,4],[5,6]],dtype='float64')   # a sub array of floats
>>> sub
array([[ 1.,  2.],
       [ 3.,  4.],
       [ 5.,  6.]])
>>> e = np.empty((3,4),dtype='object')   # an empty array of the desired shape
>>> e
array([[None, None, None, None],
       [None, None, None, None],
       [None, None, None, None]], dtype=object)
>>> dX = 1; dY = np.sqrt(3.)/2.0        # values to add to sub array per cell in e
>>> rows,cols = e.shape                 # rows and columns from 'e' shape
>>> out = [sub + [dX*i,dY*(i%2)] for i in range(0,cols)]  # create the first row
>>> for j in range(1,rows):              # create the other rows
...   out += [out[k] + [0,-dY*2*j] for k in range(cols)]    
...   
>>> arr = np.array(out)
>>> arr.shape    # expect to see ((3,4),3,2)...I think
(12, 3, 2)       
>>> arr[0:4]     #  I will let you try this to see the format

The last line just shows the format of the first 4 elements of the output array. What I was hoping to do was populate the empty array, e, in a fashion which is more elegant than my list comprehension method AND/OR how to reshape the array properly. Again, unless I am missing links in the documentation, I would have expected a 3x4 array containing 3x2 subarrays...which is not what it is showing me. I would appreciate any help or links to appropriate documentation, since, I have spent hours trolling this site and I am obviously missing some appropriate numpy terminology.

Upvotes: 0

Views: 81

Answers (1)

hpaulj
hpaulj

Reputation: 231395

The first out is a list of 4 (3,2) arrays.

np.array(out) at this stage produces a (4,3,2) array. np.array creates the highest dimension array that the data allows. In this case is concatenates those 4 arrays along a new dimension.

After the rows loop, out is a list of 12 arrays. out +=... on a list appends them.

So by the same logic, arr = np.array(out) will produce a (12,3,2) array. That could be reshaped: arr = arr.reshape(3,4,3,2).

Subarrays from arr could be copied to e, e.g.:

e[0,0] = arr[0,0]

Which raises the question, why do you want array like e? What advantage does it have over arr? arr represents 'the best of numpy's capabilities,e` tries to extend to them in poorly developed areas.


Your out list can be vectorized with something along this line:

ii = np.arange(cols)
ixy = np.array([dX*ii, dY*(ii%2)])
arr1 = sub[None,:,:] + ixy.T[:,None,:]

arr1 is a (4,3,2) array, and could be copied to the e[0,:] elements.

This could be cleaned up and extended to the other rows.


A clean way of iterating over all the elements of e, and assigning the corresponding subarray of arr uses np.ndindex (from the index_tricks module):

for i in np.ndindex(3,4):
    e[i]=arr[i]

While it is a Python level iteration, it does not involve copying data. It just copies pointers. I'm a little surprised about this, but e[i,j] points to the same data block as arr[i,j]. This is evident from the .__array_interface__ values, and by modifying entries, e.g.

e[1,1][0,0] = 30  

changes the value of arr[1,1,0,0].

Upvotes: 1

Related Questions