For a 2*N x 2*N array x, I'd like to swap rows [0:N] with rows [N:2*N] in a particular way, namely, the question I have is, if there is a 'built-in' way of 'adding / joining' slice objects to achieve this? I.e. something like:
x[N:2*N + 0:N,:]
although, the preceding does something different.
Certainly I could do things like vstack((x[N:2*N,:],x[0:N,:])), which is not really what I'm looking for, or x[[i for i in range(N)]+[i for i in range(N,2*N)],:], which probably is slow.
I think you're looking for numpy.r_, which "translates slice objects to concatenation along the first axis". It allows you to perform more complex slices along the first axis - you can concatenate multiple slices with commas: np.r_[5:10, 100:200:10, 15, 20, 0:5].
For example:
>>> import numpy as np
>>> N = 2
>>> x = np.arange(16).reshape(4, 4)
>>> x[np.r_[N:2*N, 0:N]]
array([[ 8, 9, 10, 11],
[12, 13, 14, 15],
[ 0, 1, 2, 3],
[ 4, 5, 6, 7]])
And in this specific case, you could also just np.roll it:
>>> np.roll(x, N, axis=0)
array([[ 8, 9, 10, 11],
[12, 13, 14, 15],
[ 0, 1, 2, 3],
[ 4, 5, 6, 7]])
Related
I have a n x n dimensional numpy array of eigenvectors as columns, and want to return the last v of them as another array. However, they are currently in ascending order, and I wish to return them in descending order.
Currently, I'm attempting to index as follows
eigenvector_array[:,-1:-v]
But this doesn't seem to be working. Is there a more efficient way to do this?
Given a 2d array:
In [44]: x = np.arange(15).reshape(3,5);x
Out[44]:
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
the last 3 columns:
In [45]: x[:,-3:]
Out[45]:
array([[ 2, 3, 4],
[ 7, 8, 9],
[12, 13, 14]])
and reversing their order:
In [46]: x[:,-3:][:,::-1]
Out[46]:
array([[ 4, 3, 2],
[ 9, 8, 7],
[14, 13, 12]])
Or we could reverse the order, and take the first n. x[:,::-1][:,:3]
I tried combining the selection and order, but getting the end points is trickier. Separating the operations is easier.
x[:,:-4:-1]
Lets re-write this to make it a little less confusing.
eigenvector_array[:,-1:-v]
to:
eigenvector_array[:][-1:-v]
Now remember how slicing works in python:
[start:stop:step]
If you set step. to -1 it will return them in reverse, so:
eigenvector_array[:,-1:-v:-1] should be your answer.
This question already has answers here:
Selecting Random Windows from Multidimensional Numpy Array Rows
(2 answers)
Closed 3 years ago.
I have an m x n numpy array arr, and for each column of arr, I have a given range of rows that I want to access.
I have an n x 1 array vec that describes when this range starts.
The range has some constant duration d.
How can I extract this d x n array of interest efficiently?
Can this be done by clever slicing?
My initial thought was to try something like:
arr = np.tile(np.arange(10),(4,1)).T
vec = np.array([3,4,5,4])
d = 3
vec_2 = vec+d
out = arr[vec:vec2,np.arange(n)]
But this gives the following error:
TypeError: only integer scalar arrays can be converted to a scalar index
The desired output would be the following array:
array([[3, 4, 5, 4],
[4, 5, 6, 5],
[5, 6, 7, 6],
[6, 7, 8, 7])
I could loop over d, but performance is important for this piece of code so I would prefer to vectorize it.
In [489]: arr=np.arange(24).reshape(6,4)
In [490]: vec=np.array([0,2,1,3])
Taking advantage of the recent expansion of linspace to generate several arrays:
In [493]: x = np.linspace(vec,vec+2,3).astype(int)
In [494]: x
Out[494]:
array([[0, 2, 1, 3],
[1, 3, 2, 4],
[2, 4, 3, 5]])
In [495]: arr[x, np.arange(4)]
Out[495]:
array([[ 0, 9, 6, 15],
[ 4, 13, 10, 19],
[ 8, 17, 14, 23]])
the column iteration approach:
In [498]: np.stack([arr[i:j,k] for k,(i,j) in enumerate(zip(vec,vec+3))],1)
Out[498]:
array([[ 0, 9, 6, 15],
[ 4, 13, 10, 19],
[ 8, 17, 14, 23]])
I want to add a list of elements at the end of the arrays of a list. I tried to use np.insertfunction like this :
dataForModel=np.insert(dataForModel, -1, output_recoded, axis=1)
where dataForModel is a list of arrays and sampling_timesis a 1-D list whose length is the same as len(dataForModel). So what I want is to put one (corresponding) element of output_recodedat the end of each array contained in dataForModel
The problem is, it puts output_recoded before the last column of the basic dataForModelbut I want it to be after.
For example if my data were dataForModel=[array([2,15,-3,4]), array([12,1,3,42]),array([6,8,21,-5])] and output_recoded is [101,47,82], I would like to have [array([2,15,-3,4,101]), array([12,1,3,42,47]),array([6,8,21,-5,82])]
Thanks for help
Try this:
dataForModel=np.insert(dataForModel, dataForModel.size, sampling_times, axis=1)
Example:
>>> a = np.array([2, 56, 4, 8, 564])
>>> np.insert(a, -1, [1,2,3])
array([ 2, 56, 4, 8, 1, 2, 3, 564])
>>> np.insert(a, a.size, [1,2,3])
array([ 2, 56, 4, 8, 564, 1, 2, 3])
Update:
>>> dataForModel=[np.array([2,15,-3,4]), np.array([12,1,3,42]),np.array([6,8,21,-5])]
>>> dataForModel=np.array(dataForModel)
>>> dataForModel
array([[ 2, 15, -3, 4],
[12, 1, 3, 42],
[ 6, 8, 21, -5]])
>>> output_recoded= [101,47,82]
>>> dataForModel=np.insert(dataForModel, dataForModel.shape[1], output_recoded, axis=1)
>>> dataForModel
array([[ 2, 15, -3, 4, 101],
[ 12, 1, 3, 42, 47],
[ 6, 8, 21, -5, 82]])
If you are trying to add an ending column, keep in mind the data added needs to match the dimensions of (dataForModel.shape[1],1) dimension
My first bet would be a for loop, though there are probably more efficient ways to do this:
for i in range(len(dataForModel)):
dataForModel[i] = [*dataForModel[i], sampling_times[i]]
The * will unpack the current array into a new list, though you could append as well
This is a question that comes from the post here Iterating and selecting a specific array from a multidimensional array in Python
In that post, user #Cleb solved what it was my original problem: how to perform a sum through columns in a 3d array:
import numpy as np
arra = np.arange(16).reshape(2, 2, 4)
which gives
array([[[0, 1, 2, 3],
[4, 5, 6, 7]],
[[8, 9, 10, 11],
[12, 13, 14, 15]]])
and the problem was how to perform the sum of columns in each matrix, i. e., 0 + 4, 1 + 5, ... , 8 + 12, ..., 11 + 15. It was solved by #Cleb.
Then I wondered how to do it in the case of a sum of 0 + 8, 1 + 9, ..., 4 + 12, ..., 7 + 15, (odd and even columns) which was also solved by #Cleb.
But then I wondered if there are a general idea (which can be modified in each specific case). Imagine you can add the first and the last rows and the center rows, in columns, separately, i. e., 0 + 12, 1 + 13, ..., 3 + 15, 4 + 8, 5 + 9, ..., 7 + 11.
Is there a general way? Thank you.
Depending on the how exactly arra is defined, you can shift your values appropriately using np.roll:
arra_mod = np.roll(arra, arra.shape[2])
arra_mod then looks as follows:
array([[[12, 13, 14, 15],
[ 0, 1, 2, 3]],
[[ 4, 5, 6, 7],
[ 8, 9, 10, 11]]])
Now you can simply use the command from your previous question to get your desired output:
map(sum, arra_mod)
which gives you the desired output:
[array([12, 14, 16, 18]), array([12, 14, 16, 18])]
You can also use a list comprehension
[sum(ai) for ai in arra_mod]
which gives you the same output.
If you prefer one-liner, you can therefore simply do:
map(sum, np.roll(arra, arra.shape[2]))
From the answer to this question, I learned how to sort the entries of one numpy array a by the values of another numpy array b, along a particular axis.
However, this method requires the creation of several intermediate arrays that are the same size as a, one for each dimension of a. Some of my arrays are quite large, and this becomes inconvenient. Is there a way to accomplish the same goal that uses less memory?
Would a record array serve your purposes?
>>> a = numpy.zeros((3, 3, 3))
>>> a += numpy.array((1, 3, 2)).reshape((3, 1, 1))
>>> b = numpy.arange(3*3*3).reshape((3, 3, 3))
>>> c = numpy.array(zip(a.flatten(), b.flatten()), dtype=[('f', float), ('i', int)]).reshape(3, 3, 3)
>>> c.sort(axis=0)
>>> c['i']
array([[[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8]],
[[18, 19, 20],
[21, 22, 23],
[24, 25, 26]],
[[ 9, 10, 11],
[12, 13, 14],
[15, 16, 17]]])
A cleaner way to generate the coupled array:
>>> c = numpy.rec.fromarrays([a, b], dtype=[('f', float), ('i', int)])
or
>>> c = numpy.rec.fromarrays([a, b], names='f, i')