How do I create a multi-dimensional index array? - python

I want to create a 3d array where basically the content is identical to the indeces used to access it. So m[2,5] would result in array([2, 5]).
I couldn't find an obvious solution with the numpy functions indices, ogrid, concatenate, etc.
At the moment I'm using this, but was wondering whether there is a solution that makes better use of the API:
a, b = 3, 4
m = np.ones((a, b, 2))
for x in range(a):
m[x,:, 1] = np.array(range(b))
for y in range(b):
m[:,y,0] = np.array(range(a))

Try np.mgrid:
a, b = 3, 4
m = np.mgrid[:a,:b].transpose(1,2,0)
print(m[1,2])
# array([1, 2])

Related

Slice an array to exclude a single element

I would like to slice a numpy array so that I can exclude a single element from it.
For example, like this:
a = numpy.array([1,2,3,4,5])
b = a[0:1::3:4]
b = [1 2 4 5]
Only that this does not work, so either I am doing something wrong, or it isn't possible.
If you are going to repeatedly 'delete' one item at a time, I'd suggest using a boolean mask:
In [493]: a = np.arange(100)
In [494]: mask = np.ones(a.shape, dtype=bool)
In [495]: for i in [2,5,9,20,3,26,40,60]:
...: mask[i]=0
...: a1 = a[mask]
In [496]: a1.shape
Out[496]: (92,)
That's effectively what np.delete does when given a list or array of deletes
In [497]: a2 = np.delete(a, [2,5,9,20,3,26,40,60])
In [498]: np.allclose(a1,a2)
Out[498]: True
For a single element is joins two slices - either by concatenate or copying to result array of the right size. In all cases we have to make a new array.
One exclusion or many, you seek an discontinuous selection of the elements of the original. That can't be produced with a view, which uses shape and strides to select a regular subset of the original.
You need to do something like below
a = np.array([1,2,3,4,5])
b = a[:2]
c = a[3:]
print ( b )
print ( c )
z= np.concatenate((b,c),axis=None)
print ( z )
Output:
[1 2]
[4 5]
[1 2 4 5]
Hence here everything other than 3 is in new numpy.ndarray z here.
Other way is to use to use np.delete function as shown in one the answers where you can provide list of indexes to be deleted inside the [] where list contains coma seperated index to be deleted.
a = np.array([15,14,13,12,11])
a4=np.delete(a,[1,4])
print(a4)
output is :
[15 13 12]
import numpy as np
a = np.array([1,2,3,4,5])
result = np.delete(a,2)
result = [1,2,4,5]
You could always use sets of slicing
b = a[:2]+a[3:]
Will return [1, 2, 4, 5]
for a numpy return value you could do 2 slices and concatenate the results.
b = a[3:]
c = a[:2]
numpy.concatenate([c,b])
Will return
array([1, 2, 4, 5])

numpy multidimensional (3d) matrix multiplication

I get two 3d matrix A (32x3x3) and B(32x3x3), and I want to get matrix C with dimension 32x3x3. The calculation can be done using loop like:
a = numpy.random.rand(32, 3, 3)
b = numpy.random.rand(32, 3, 3)
c = numpy.random.rand(32, 3, 3)
for i in range(32):
c[i] = numpy.dot(a[i], b[i])
I believe there must be a more efficient one-line solution to this problem. Can anybody help, thanks.
You could do this using np.einsum:
In [142]: old = orig(a,b)
In [143]: new = np.einsum('ijk,ikl->ijl', a, b)
In [144]: np.allclose(old, new)
Out[144]: True
One advantage of using einsum is that you can almost read off what it's doing from the indices: leave the first axis alone (i), and perform a matrix multiplication on the last two (jk,kl->jl)).

Element-wise array maximum function in NumPy (more than two arrays)

I'm trying to return maximum values of multiple array in an element-wise comparison. For example:
A = array([0, 1, 2])
B = array([1, 0, 3])
C = array([3, 0, 4])
I want the resulting array to be array([3,1,4]).
I wanted to use numpy.maximum, but it is only good for two arrays. Is there a simple function for more than two arrays?
With this setup:
>>> A = np.array([0,1,2])
>>> B = np.array([1,0,3])
>>> C = np.array([3,0,4])
You can either do:
>>> np.maximum.reduce([A,B,C])
array([3, 1, 4])
Or:
>>> np.vstack([A,B,C]).max(axis=0)
array([3, 1, 4])
I would go with the first option.
You can use reduce. It repeatedly applies a binary function to a list of values...
For A, B and C given in question...
np.maximum.reduce([A,B,C])
array([3,1,4])
It first computes the np.maximum of A and B and then computes the np.maximum of (np.maximum of A and B) and C.
You can also use:
np.column_stack([A, B, C]).max(axis=1)
The result is the same as the solutions from the other answers.
I use Pandas more heavily than NumPy so for me it's easier to think of 1D arrays as something similar to Pandas Series. The above would be equivalent to:
pd.concat([A, B, C], axis=1).max(axis=1)

How can I iterate over an 1D array and build a 2D array in Numpy?

If I have an 1D numpy.ndarray b and a Python function f that I want to vectorize, this is very easy using the numpy.vectorize function:
c = numpy.vectorize(f)(a).
But if f returns a 1D numpy.ndarray instead of a scalar, how can I build a 2D numpy.ndarray instead? (That is, I want every 1D numpy.ndarray returned from f to become a row in the new 2D numpy.ndarray.)
Example:
def f(x):
return x * x
a = numpy.array([1,2,3])
c = numpy.vectorize(f)(a)
def f_1d(x):
return numpy.array([x, x])
a = numpy.ndarray([1,2,3])
d = ???(f_1d)(a)
In the above example c would become array([1, 4, 9]). What should ??? be replaced with if d should become array([[1, 1], [2, 2], [3, 3]])?
Could do this instead:
def f_1d(x):
return (x,x)
d = numpy.column_stack(numpy.vectorize(f_1d)(a))
will output:
array([[1, 1],
[2, 2],
[3, 3]])
I think you're looking for reshape and repeat
def f(x):
return x * x
a = numpy.array([1,2,3])
b= numpy.vectorize(f)(a)
c = numpy.repeat(b.reshape( (-1,1) ),2, axis=1)
print c
output:
[[1 1]
[4 4]
[9 9]]
You can also just set the array.shape tuple directly.
It may be worthwhile to know that you can accomplish the same as vectorize using map, if you ever need to write pure python. b= numpy.vectorize(f)(a) would become b=map(f,a)
Using this kind of approach, it becomes unnecessary to have your f_1d at all, since all it seems to do is duplicate information, which is done best by numpy.repeat.
Also, this version is a bit faster, but this only matters if you're dealing with large arrays.

Find whether a numpy array is a subset of a larger array in Python

I have 2 arrays, for the sake of simplicity let's say the original one is a random set of numbers:
import numpy as np
a=np.random.rand(N)
Then I sample and shuffle a subset from this array:
b=np.array() <------size<N
The shuffling I do do not store the index values, so b is an unordered subset of a
Is there an easy way to get the original indexes of b, so they are in the same order as a, say, if element 2 of b has the index 4 in a, create an array of its assignation.
I could use a for cycle checking element by element, but perhaps there is a more pythonic way
Thanks
I think the most computationally efficient thing to do is to keep track of the indices that associate b with a as b is created.
For example, instead of sampling a, sample the indices of a:
indices = random.sample(range(len(a)), k) # k < N
b = a[indices]
On the off chance a happens to be sorted you could do:
>>> from numpy import array
>>> a = array([1, 3, 4, 10, 11])
>>> b = array([11, 1, 4])
>>> a.searchsorted(b)
array([4, 0, 2])
If a is not sorted you're probably best off going with something like #unutbu's answer.

Categories

Resources