How to resample a Numpy array of arbitrary dimensions? - python

There is scipy.misc.imresize for resampling the first two dimensions of 3D arrays. It also supports bilinear interpolation. However, there does not seem to be an existing function for resizing all dimensions of arrays with any number of dimensions. How can I resample any array given a new shape of the same rank, using multi-linear interpolation?

You want scipy.ndimage.zoom, which can be used as follows:
>>> x = np.arange(8, dtype=np.float_).reshape(2, 2, 2)
>>> scipy.ndimage.zoom(x, 1.5, order=1)
array([[[ 0. , 0.5, 1. ],
[ 1. , 1.5, 2. ],
[ 2. , 2.5, 3. ]],
[[ 2. , 2.5, 3. ],
[ 3. , 3.5, 4. ],
[ 4. , 4.5, 5. ]],
[[ 4. , 4.5, 5. ],
[ 5. , 5.5, 6. ],
[ 6. , 6.5, 7. ]]])
Note that this function always preserves the boundaries of the image, essentially resampling a mesh with a node at each pixel center. You might want to look at other functions in scipy.ndimage if you need more control over exactly where the resampling occurs

Related

Combination of rows in numpy.ndarray

I have the following numpy.ndarray
S=np.array([[[ -0.6, -0.2, 0. ],
[-60. , 2. , 0. ],
[ 6. , -20. , 0. ]],
[[ -0.4, -0.8, 0. ],
[-40. , 8. , 0. ],
[ 4. , -80. , 0. ]]])
I want to find all the possible combinations of sum of each row (sum of individual elements of a row except the last column) of S[0,:,:] with each row of S[1,:,:], i.e., my desired result is (order does not matter):
array([[-1, -1],
[-40.6, 7.8],
[3.4, -80.2],
[-60.4, 1.2],
[-100, 10],
[-56, -78],
[5.6, -20.8],
[-34, -12],
[10, -100]])
which is a 9-by-2 array resulting from 9 possible combinations of S[0,:,:] and S[1,:,:]. Although I have used a particular shape of S here, the shape may vary, i.e., for
x,y,z = np.shape(S)
in the above problem, x=2, y=3, and z=3, but these values may vary. Therefore, I am seeking for a generalized version.
Your help will be highly appreciated. Thank you for your time!
(Please no for loops if possible. It is pretty trivial then.)
You can use broadcast like this:
(S[0,:,None, :-1] + S[1,None,:,:-1]).reshape(-1,2)
Output:
array([[ -1. , -1. ],
[ -40.6, 7.8],
[ 3.4, -80.2],
[ -60.4, 1.2],
[-100. , 10. ],
[ -56. , -78. ],
[ 5.6, -20.8],
[ -34. , -12. ],
[ 10. , -100. ]])

How can I simply filter a 3d numpy array by its 1st column values?

Suppose I have a 3D numpy array like this:
data = np.array([[[1,2,3,4],[1,2.5,3,5]],
[[116,230,450,430],[80,100,300,320]],
[[60,100,120,80],[50,80,100,90]]])
How can I simply extract from it a 3D numpy array of same shape with a condition on axis 0, for example selecting those "rows" for which axis 0 < 3? A naïve way would be
data[data[0]<3]
But this fails:
IndexError: boolean index did not match indexed array along dimension 0; dimension is 3 but corresponding boolean dimension is 2
See my comment above, but from your data I am guessing you want the rows with any values less than 3. If so you could do:
data[(data<3).any(axis=2)]
>>> array([[1. , 2. , 3. , 4. ],
[1. , 2.5, 3. , 5. ]])
EDIT1:
Solution can be achieved using transposition to match up the axis dimensions:
data.T[(data[0]<3).any(axis=0).T].T
>>> array([[[ 1. , 2. ],
[ 1. , 2.5]],
[[116. , 230. ],
[ 80. , 100. ]],
[[ 60. , 100. ],
[ 50. , 80. ]]])
EDIT2:
Another method that does not involve transposing. To apply the mask (data[0]<3).any(axis=0) onto the original data array the axes shapes must match. The shape of the mask is (4,) and data.shape = (3, 2, 4), so we need to apply the mask to the last axis as:
data[..., (data[0]<3).any(axis=0)]
>>> array([[[ 1. , 2. ],
[ 1. , 2.5]],
[[116. , 230. ],
[ 80. , 100. ]],
[[ 60. , 100. ],
[ 50. , 80. ]]])

turning a list of numpy.ndarray to a matrix in order to perform multiplication

i have vectors of this form :
test=np.linspace(0,1,10)
i want to stack them horizontally in order to make a matrix .
problem is that i define them in a loop so the first stack is between an empty matrix and the first column vector , which gives the following error:
ValueError: all the input arrays must have same number of dimensions
bottom line - i have a for loop that with every iteration creates a vector p1 and i want to add it to a final matrix of the form :
[p1 p2 p3 p4] which i could then do matrix operations on such as multiplying by the transposed etc
If you've got a list of 1D arrays that you want horizontally stacked, you could convert them all to column first, but it's probably easier to just vertically stack them and then transpose:
In [6]: vector_list = [np.linspace(0, 1, 10) for _ in range(3)]
In [7]: np.vstack(vector_list).T
Out[7]:
array([[0. , 0. , 0. ],
[0.11111111, 0.11111111, 0.11111111],
[0.22222222, 0.22222222, 0.22222222],
[0.33333333, 0.33333333, 0.33333333],
[0.44444444, 0.44444444, 0.44444444],
[0.55555556, 0.55555556, 0.55555556],
[0.66666667, 0.66666667, 0.66666667],
[0.77777778, 0.77777778, 0.77777778],
[0.88888889, 0.88888889, 0.88888889],
[1. , 1. , 1. ]])
How did you get this dimension error? What does empty array have to do with it?
A list of arrays of the same length:
In [610]: alist = [np.linspace(0,1,6), np.linspace(10,11,6)]
In [611]: alist
Out[611]:
[array([0. , 0.2, 0.4, 0.6, 0.8, 1. ]),
array([10. , 10.2, 10.4, 10.6, 10.8, 11. ])]
Several ways of making an array from them:
In [612]: np.array(alist)
Out[612]:
array([[ 0. , 0.2, 0.4, 0.6, 0.8, 1. ],
[10. , 10.2, 10.4, 10.6, 10.8, 11. ]])
In [614]: np.stack(alist)
Out[614]:
array([[ 0. , 0.2, 0.4, 0.6, 0.8, 1. ],
[10. , 10.2, 10.4, 10.6, 10.8, 11. ]])
If you want to join them in columns, you can transpose one of the above, or use:
In [615]: np.stack(alist, axis=1)
Out[615]:
array([[ 0. , 10. ],
[ 0.2, 10.2],
[ 0.4, 10.4],
[ 0.6, 10.6],
[ 0.8, 10.8],
[ 1. , 11. ]])
np.column_stack is also handy.
In newer numpy versions you can do:
In [617]: np.linspace((0,10),(1,11),6)
Out[617]:
array([[ 0. , 10. ],
[ 0.2, 10.2],
[ 0.4, 10.4],
[ 0.6, 10.6],
[ 0.8, 10.8],
[ 1. , 11. ]])
You don't specify how you create the 'empty array' and how you attempt to stack. I can't exactly recreate the error message (full traceback would have helped). But given that message did you check the number of dimensions of the inputs? Did they match?
Array stacking in a loop is tricky. You have to pay close attention to the shapes, especially of the initial 'empty' array. There isn't a close analog to the empty list []. np.array([]) is 1d with shape (1,). np.empty((0,6)) is 2d with shape (0,6). Also all the stacking functions create a new array with each call (non operate in-place), so they are inefficient (compared to list append).

Generating multiple vandermonde arrays

I have a function that creates a 2-dim array, a Vandermonde matrix and is called as:
vandermonde(generator, rank)
Where generator is a n-sized array for example
generator = np.array([-1/2, 1/2, 3/2, 5/2, 7/2, 9/2])
and rank=4
Then I need to create 4 Vandermonde matrices (because rank=4) skewed by h in my space (that h is arbitrary here, lets call h=1).
Therefore I came with the following deterministic code:
V = np.array([
vandermonde(generator-0*h, rank),
vandermonde(generator-1*h, rank),
vandermonde(generator-2*h, rank),
vandermonde(generator-3*h, rank)
])
Then I want instead do multiple manual calls to vandermonde I used a for-loop as in:
V=[]
for i in range(rank):
V.append(vandermonde(generator - h*i, rank))
V = np.array(V)
This approach works fine, but seems too "patchy". I tried a np.append approach as below:
M = np.array([])
for i in range(rank):
M = np.append(M,[vandermonde(generator - h*i, rank)])
But didn't worked as I expected, seems np.append expand the array instead to create a new element.
My questions are:
How can I not use standard Python lists, use directly a np approach cause np.append seems not behave as I expect, instead it just grow that array instead add a new array element
Is there any more direct numpy approaches to this?
My vandermonde function is:
def vandermonde(generator, rank=None):
"""Returns a vandermonde matrix
If rank not passwd returns a square vandermonde matrix
"""
if rank is None:
rank = len(generator)
return np.tile(generator,(rank,1)) ** np.array(range(rank)).reshape((rank,1))
The expected answer is a 3 dimensional array with size (generator, rank, rank) where each element is one of the generator skewed vandermonde matrices. For the constants above(generator, rank, h) we have:
V= array([[[ 1. , 1. , 1. , 1. , 1. , 1. ],
[ -0.5 , 0.5 , 1.5 , 2.5 , 3.5 , 4.5 ],
[ 0.25, 0.25, 2.25, 6.25, 12.25, 20.25],
[ -0.12, 0.12, 3.38, 15.62, 42.88, 91.12]],
[[ 1. , 1. , 1. , 1. , 1. , 1. ],
[ -1.5 , -0.5 , 0.5 , 1.5 , 2.5 , 3.5 ],
[ 2.25, 0.25, 0.25, 2.25, 6.25, 12.25],
[ -3.38, -0.12, 0.12, 3.38, 15.62, 42.88]],
[[ 1. , 1. , 1. , 1. , 1. , 1. ],
[ -2.5 , -1.5 , -0.5 , 0.5 , 1.5 , 2.5 ],
[ 6.25, 2.25, 0.25, 0.25, 2.25, 6.25],
[-15.62, -3.38, -0.12, 0.12, 3.38, 15.62]],
[[ 1. , 1. , 1. , 1. , 1. , 1. ],
[ -3.5 , -2.5 , -1.5 , -0.5 , 0.5 , 1.5 ],
[ 12.25, 6.25, 2.25, 0.25, 0.25, 2.25],
[-42.88, -15.62, -3.38, -0.12, 0.12, 3.38]]])
Some related ideas can be found in this discussion on: efficient-way-to-compute-the-vandermonde-matrix
Use broadcasting to get the final 3D array in a vectorized manner -
r = np.arange(rank)
V_out = (generator - h*r[:,None,None]) ** r[:,None]
We can also use cumprod to achieve the exponential values for another solution -
gr = np.repeat(generator - h*r[:,None,None], rank, axis=1)
gr[:,0] = 1
out = gr.cumprod(1)

Meshgrid a N-columned matrix in Numpy (or smth else)

Python version: 2.7
I have the following numpy 2d array:
array([[ -5.05000000e+01, -1.05000000e+01],
[ -4.04000000e+01, -8.40000000e+00],
[ -3.03000000e+01, -6.30000000e+00],
[ -2.02000000e+01, -4.20000000e+00],
[ -1.01000000e+01, -2.10000000e+00],
[ 7.10542736e-15, -1.77635684e-15],
[ 1.01000000e+01, 2.10000000e+00],
[ 2.02000000e+01, 4.20000000e+00],
[ 3.03000000e+01, 6.30000000e+00],
[ 4.04000000e+01, 8.40000000e+00]])
If I wanted to find all the combinations of the first and the second columns, I would use np.array(np.meshgrid(first_column, second_column)).T.reshape(-1,2). As a result, I would get a 100*1 matrix with 10*10 = 100 data points. However, my matrix can have 3, 4, or more columns, so I have a problem of using this numpy function.
Question: how can I make an automatically meshgridded matrix with 3+ columns?
UPD: for example, I have the initial array:
[[-50.5 -10.5]
[ 0. 0. ]]
As a result, I want to have the output array like this:
array([[-10.5, -50.5],
[-10.5, 0. ],
[ 0. , -50.5],
[ 0. , 0. ]])
or this:
array([[-50.5, -10.5],
[-50.5, 0. ],
[ 0. , -10.5],
[ 0. , 0. ]])
You could use * operator on the transposed array version that unpacks those columns sequentially. Finally, a swap axes operation is needed to merge the output grid arrays as one array.
Thus, one generic solution would be -
np.swapaxes(np.meshgrid(*arr.T),0,2)
Sample run -
In [44]: arr
Out[44]:
array([[-50.5, -10.5],
[ 0. , 0. ]])
In [45]: np.swapaxes(np.meshgrid(*arr.T),0,2)
Out[45]:
array([[[-50.5, -10.5],
[-50.5, 0. ]],
[[ 0. , -10.5],
[ 0. , 0. ]]])

Categories