Selecting axis form multidimensional arrays with an array - python

I am trying to select a subset of a multidimensional array using another array, so for example, if I have:
a=np.linspace(1,30,30)
a=a.reshape(5,3,2)
I would like to take the subset [:,0,1], which I can do by saying
a_subset=a[:,0,1]
but, is there any way to define an array/list specifying that subset and then subtract it? The idea is to do something like:
b=[:,0,1]
a_subset=a[b]
which does not work as ":" is not accepted as item ("SyntaxError: invalid syntax")

You can do this using numpy.index_exp (docs) as follows:
import numpy as np
a = np.linspace(1, 30, 30)
a = a.reshape(5, 3, 2)
b = np.index_exp[:,0,1]
a_subset = a[b]

Related

Splitting numpy multidimensional array based on indices stored in another array or list

I have a numpy multidimensional array with shape = (12,2,3,3)
import numpy as np
arr = np.arange(12*2*3*3).reshape((12,2,3,3))
I need to select those elements based on the 2nd dimension where the dindices are stored in another list
indices = [0,1,0,0,1,1,0,1,1,0,1,1]
in one array, and the rest in another array.
the output in either case should be in another array of shape (12,3,3)
arr2 = np.empty((arr.shape[0],*arr.shape[-2:]))
I could do it using a for loop
for i, ii in enumerate(indices):
arr2[i] = arr[i, indices[ii],...]
However, I am searching for a one liner.
When I try indexing using the list as indices
test = arr[:,indices,...]
I get test of shape (12,12,3,3) instead of (12,3,3). Could you help me please?
You can use np.arange for indexing the first dimension:
test = arr[np.arange(arr.shape[0]),indices,...]
or just the python range function:
test = arr[range(arr.shape[0]),indices,...]

Multidimensional numpy array appending with Python

In Python, I can concatenate two arrays like below,
myArray = []
myArray += [["Value1", "Value2"]]
I can then access the data by indexing the 2 dimensions of this array like so
print(myArray[0][0])
which will output:
Value1
How would I go about achieving the same thing with Numpy?
I tried the numpy append function but that only ever results in single dimensional arrays for me, no matter how many square brackets I put around the value I'm trying to append.
If you know the dimension of the final array then you could use np.vstack
>>> import numpy as np
>>> a = np.array([]).reshape(0,2)
>>> b = np.array([['Value1', 'Value2']])
>>> np.vstack([a,b])
array([['Value1', 'Value2']], dtype='<U32')

Accessing specific element of an array

I'm unsure of how to access an element in an array (of arrays?). Basically, I need to be able to assign random numbers to a series of arrays but I'm not sure how indexing works.
array_20 = np.zeros((5,10))
a = [[array_20]]*10
#This gives me 10 arrays of 5x10. I'd like to be able to then assign random
#numbers to all of the elements.
You could use numpy.random.rand like so:
import numpy as np
a = np.random.rand(10, 5, 10)
You can then index a like a python list. (i.e. a[1][2][0])

Shape manipulation of numpy array

The 'd' is given condition however it was obtained.
I want to get 'result' in the required shape.
I tried it as follows; but it's beyond my imagination.
import numpy as np
data = [np.ones((300,1)), np.ones((300,5)), np.ones((300,3))]
result = []
for d in data:
**print np.shape(np.array(d))**
result.append(d)
print np.shape(np.array(result))
The result should be in this shape:
(300, 1+5+3) = (300,9)
Can someone help me?
I got
ValueError: could not broadcast input array from shape (300,1) into shape (300)
EDIT:
data is just to make this question; it is just representation of my large program. given condition is d, which is a list but different shapes are list are generating from the for loop.
3 2d arrays the differ in the last dimension can be joined on that dimension
Np.concatenate(data, axis=1)
hstack does the same.
In my comment I suggested axis 0, but that was a quick response and I didn't a chance test it.
When you try ideas and they fail, show us what was wrong. You list a ValueError but don't show where that occurred. What operation.
Your comments make a big deal about d, but you don't show how d might differ from the elements of data.
You can also try numpy.column_stack, which essentially does numpy.concatenate under the hood.
Example use
In [1]: import numpy as np
In [2]: data = [np.ones((300,1)), np.ones((300,5)), np.ones((300,3))]
In [3]: out = np.column_stack(data)
In [4]: out.shape
Out[4]: (300, 9)
Your result is a Python list. In fact it is a list with the exact same contents as the original data. You are trying to concatenate arrays horizontally (along the second dimension), so you need to use numpy.hstack:
import numpy as np
data = []
for d in some_source:
data.append(d)
result = np.hstack(data)
print result.shape
If some_source is a list, a generator, or any other iterable, you can do this even more concisely:
result = np.hstack(some_source)
You want to stack the elements horizontally (if you imagine each element as a matrix with 300 rows and variable number of columns), i.e.
import numpy as np
data = [np.ones((300,1)), np.ones((300,5)), np.ones((300,3))]
result = np.hstack(data)
If you only have access to an iterator that generates elements d you can achieve the same as follows:
result = np.hstack([d for d in some_iterator_that_generates_your_ds])
try:
import numpy as np
data = [np.ones((300,1)), np.ones((300,5)), np.ones((300,3))]
result = []
print(len(data))
for d in data:
result.append(np.hstack(d))
print(result.shape)
This should do the job. You can also try:
import numpy as np
data = np.ones((300,1)), np.ones((300,5)), np.ones((300,3))
result = np.vstack(data[-1])
print(result.shape)
Both of which would yield (300, 3) as output.
If you're looking for (300, 9), you can do as follows:
result = np.hstack(data)
Finally, if you'd like your results to be in list() as opposed to numpy.array or numpy.matrix, you can just stick a .tolist() to the end, like so: result.tolist().

Simple question: In numpy how do you make a multidimensional array of arrays?

Right, perhaps I should be using the normal Python lists for this, but here goes:
I want a 9 by 4 multidimensional array/matrix (whatever really) that I want to store arrays in. These arrays will be 1-dimensional and of length 4096.
So, I want to be able to go something like
column = 0 #column to insert into
row = 7 #row to insert into
storageMatrix[column,row][0] = NEW_VALUE
storageMatrix[column,row][4092] = NEW_VALUE_2
etc..
I appreciate I could be doing something a bit silly/unnecessary here, but it will make it ALOT easier for me to have it structured like this in my code (as there's alot of these, and alot of analysis to be done later).
Thanks!
Note that to leverage the full power of numpy, you'd be much better off with a 3-dimensional numpy array. Breaking apart the 3-d array into a 2-d array with 1-d values
may complicate your code and force you to use loops instead of built-in numpy functions.
It may be worth investing the time to refactor your code to use the superior 3-d numpy arrays.
However, if that's not an option, then:
import numpy as np
storageMatrix=np.empty((4,9),dtype='object')
By setting the dtype to 'object', we are telling numpy to allow each element of storageMatrix to be an arbitrary Python object.
Now you must initialize each element of the numpy array to be an 1-d numpy array:
storageMatrix[column,row]=np.arange(4096)
And then you can access the array elements like this:
storageMatrix[column,row][0] = 1
storageMatrix[column,row][4092] = 2
The Tentative NumPy Tutorial says you can declare a 2D array using the comma operator:
x = ones( (3,4) )
and index into a 2D array like this:
>>> x[1,2] = 20
>>> x[1,:] # x's second row
array([ 1, 1, 20, 1])
>>> x[0] = a # change first row of x
>>> x
array([[10, 20, -7, -3],
[ 1, 1, 20, 1],
[ 1, 1, 1, 1]])

Categories