Reputation:
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
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