How can I obtain value of a ndarray from a list that contains coordinates of a n-D point as efficient as possible.
Here an implementation for 3D :
1 arr = np.array([[[0, 1]]])
2 points = [[0, 0, 1], [0, 0, 0]]
3 values = []
4 for point in points:
5 x, y, z = point
6 value.append(arr[x, y, z])
7 # values -> [1, 0]
If this is not possible, is there a way to generalize lines 5-6 to nD?
I am sure there is way to achieve this using fancy indexing. Here is a way to do without the for-loop:
arr = np.array([[[0, 1]]])
points = np.array([[0, 0, 1], [0, 0, 0]])
x,y,z = np.split(points, 3, axis=1)
arr[x,y,z]
output (values):
array([[1],
[0]])
Alternatively, you could use tuple unpacking as suggested by the comment:
arr[(*points.T,)]
output:
array([1, 0])
Based on the Numpy documentation for indexing, you can easily do that, as long as you use tuples instead of lists:
arr = np.array([[[0, 1]]])
points = [(0, 0, 1), (0, 0, 0)]
values = []
for point in points:
value.append(arr[point])
# values -> [1, 0]
This works independent of dimensionality of the Numpy array involved.
Bonus: In addition to appending to a list, you can also use the Python slice function to extract ranges directly:
arr = np.array([[[0, 1]]])
points = (0, 0, slice(2) )
vals = arr[points]
# --> [0 1] (a Numpy array!)
Related
I have a 2D array I created using this,
import numpy as np
arr = np.arange(4)
arr_2d = arr.reshape(2,2)
The array looks like this
print(arr_2d)
[[0, 1],
[2, 3]]
I am trying to get the location of each entry in arr_2d as an x, y coordinate, and eventually get an array that looks like this,
print(full_array)
[[0, 0, 0],
[1, 0, 1],
[2, 1, 0],
[3, 1, 1]]
Where the first column contains the values in arr_2d, the second column contains each value's x (or row) coordinate and the third column contains each value's y (or column) coordinate. I tried flattening arr_2d and enumerating to get the index of each entry, but I was unable to get it in this form. Any help will be much appreciated.
You can use np.unravel_index():
x = arr_2d.flatten()
r = np.vstack((x,np.unravel_index(np.arange(arr_2d.size),arr_2d.shape))).T
# r = array([[0, 0, 0],
# [1, 0, 1],
# [2, 1, 0],
# [3, 1, 1]], dtype=int64)
Both flatten() and np.unravel_index() use by default a row-major order, so we knows that the right order is preserved.
Perhaps not the nicest way, but it works (assuming this is what you are after):
import numpy as np
arr = np.arange(4)
arr_2d = arr.reshape(2,2)
arr_2d[1][0] = 5 # to illustrate a point
print(arr_2d)
dimensions = arr_2d.shape
for y in range(dimensions[0]):
for x in range(dimensions[1]):
print(arr_2d[x][y], " (x:", x, " y:", y, ")")
renders:
[[0 1]
[5 3]]
0 (x: 0 y: 0 )
1 (x: 1 y: 0 )
5 (x: 0 y: 1 )
3 (x: 1 y: 1 )
which you can just put in another array
I need help to find an efficient method (as fast as possible) to transform a numpy array of labels into a numpy array of colors.
Let's take a simple exemple:
A contains labels (ints):
A = [0,45,45,22,0,45,45,22]
B contains all the labels:
B = np.unique(A) = [0,45,22]
C contains RGB values:
C = [[1,0,0], [0,1,0], [0,0,1]]
and the ith element of C is the color of the ith label in B. For example, color of label 45 is [0,1,0].
According to this, A should be transform to:
[[1,0,0], [0,1,0], [0,1,0], [0,0,1], ...]
I already tried the following piece of code, but it is very slow:
result = np.array([C[np.where(B==x)[0][0]] for x in A])
Does someone knows a more efficient solution ?
Thanks in advance :)
You can use np.unique's inverse index for that:
import numpy as np
A = np.array([0,45,45,22,0,45,45,22])
C = np.array([[1,0,0], [0,1,0], [0,0,1]])
_, inverse_idx = np.unique(A, return_inverse=True)
result = C[inverse_idx]
# array([[1, 0, 0], [0, 0, 1], [0, 0, 1], [0, 1, 0], [1, 0, 0], [0, 0, 1], [0, 0, 1], [0, 1, 0]])
Important note: np.unique returns values and indices as a sorted array, so np.unique(A) gives [0, 22, 35], and not [0, 45, 22]. If you do want to have it in the order in which they appear, it will require an additional operation using the original index of the values of A:
import numpy as np
A = np.array([0,45,45,22,0,45,45,22])
C = np.array([[1,0,0], [0,1,0], [0,0,1]])
_, idx, inverse_idx = np.unique(A, return_index=True, return_inverse=True)
result = C[idx.argsort()[inverse_idx]]
# array([[1, 0, 0], [0, 1, 0], [0, 1, 0], [0, 0, 1], [1, 0, 0], [0, 1, 0], [0, 1, 0], [0, 0, 1]])
A = np.array([0,45,45,22,0,45,45,22])
B = np.unique(A)
C = np.array([[1,0,0], [0,1,0], [0,0,1]])
from numba import njit
#njit
def f(arr, labels, colors):
result = np.zeros((len(arr), 3))
for i, label in enumerate(labels):
result[arr==label] = colors[i]
return result
compile the function using a single element from A:
f(A[:1], B, C)
Now:
result = f(A, B, C)
It requires 9.5367431640625e-05 sec on my machine, vs 3.123283e-04 sec of your solution
I also tried my funtion on an 1'000'000 numbers A and it required 0.0359194278717041 vs 5.217064619064331 sec of your solution
I have asked a previous question, but I think my example was not clear. I am still trying to subtract two different sizes of numpy arrays from a list of numpy arrays. For example:
####Data####
### For same size numpy arrays the subtraction works fine!!!!###
easy_data= [[1,2,3],[2,2,2]],[[1,2,3],[1,2,5]]
d = [np.array(i) for i in easy_data] # List of numpy arrays
res = d[1] - d[0]
>> array([[ 0, 0, 0],
[-1, 0, 3]])
##### Current Issue ####
data = [[1,2,3],[2,2,2]],[[1,2,3],[1,2,5],[1,1,1]]
d = [np.array(i) for i in data]
res = d[1] - d[0] #### As the sizes are different I can't subtract them ###
Desired Output
array([[ 0, 0, 0],
[-1, 0, 3],[1,1,1])
I am kind of slow getting how to work with numpy arrays but I can't figure out how to make this work? Can anybody help me?
It's easiest to operate on a slice. If you do not want to erase the original array, use a copy:
>>> res=d[1].copy()
>>> res[:d[0].shape[0]]-=d[0]
>>> res
array([[ 0, 0, 0],
[-1, 0, 3],
[ 1, 1, 1]])
From Getting indices of both zero and nonzero elements in array, I can get indicies of non-zero elements in a 1 D array in numpy like this:
indices_nonzero = numpy.arange(len(array))[~bindices_zero]
Is there a way to extend it to a 2D array?
You can use numpy.nonzero
The following code is self-explanatory
import numpy as np
A = np.array([[1, 0, 1],
[0, 5, 1],
[3, 0, 0]])
nonzero = np.nonzero(A)
# Returns a tuple of (nonzero_row_index, nonzero_col_index)
# That is (array([0, 0, 1, 1, 2]), array([0, 2, 1, 2, 0]))
nonzero_row = nonzero[0]
nonzero_col = nonzero[1]
for row, col in zip(nonzero_row, nonzero_col):
print("A[{}, {}] = {}".format(row, col, A[row, col]))
"""
A[0, 0] = 1
A[0, 2] = 1
A[1, 1] = 5
A[1, 2] = 1
A[2, 0] = 3
"""
You can even do this
A[nonzero] = -100
print(A)
"""
[[-100 0 -100]
[ 0 -100 -100]
[-100 0 0]]
"""
Other variations
np.where(array)
It is equivalent to np.nonzero(array)
But, np.nonzero is preferred because its name is clear
np.argwhere(array)
It's equivalent to np.transpose(np.nonzero(array))
print(np.argwhere(A))
"""
[[0 0]
[0 2]
[1 1]
[1 2]
[2 0]]
"""
A = np.array([[1, 0, 1],
[0, 5, 1],
[3, 0, 0]])
np.stack(np.nonzero(A), axis=-1)
array([[0, 0],
[0, 2],
[1, 1],
[1, 2],
[2, 0]])
np.nonzero returns a tuple of arrays, one for each dimension of a, containing the indices of the non-zero elements in that dimension.
https://docs.scipy.org/doc/numpy/reference/generated/numpy.nonzero.html
np.stack joins this tuple array along a new axis. In our case, the innermost axis also known as the last axis (denoted by -1).
The axis parameter specifies the index of the new axis in the dimensions of the result. For example, if axis=0 it will be the first dimension and if axis=-1 it will be the last dimension.
New in version 1.10.0.
https://docs.scipy.org/doc/numpy/reference/generated/numpy.stack.html
i have created matrix with 4 main informations about the nodes of a graph that i want to manipulate and i'm trying to save them as an array of arrays.
and with an associative array ordered to iterate on a certain information
this is the matrix with my informations
nodes = [[0 for x in range(4)] for y in range(n)]
for i in range(nodeNumber+1):
nodes[i] = info1[i], info2[i] , info[3] , i
How do i create the same matrix with numpy?
i've tried to create a matrix from my 'nodes' but it's like i've an array of tuples and not a matrix, as numpy does not see it as one
In [114]: n=3
In [115]: nodes = [[0 for x in range(4)] for y in range(n)]
In [116]: nodes
Out[116]: [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
So you have created a list, which contains lists
In [117]: for i in range(3):
...: nodes[i] = 1,2,3,i
...:
In [118]: nodes
Out[118]: [(1, 2, 3, 0), (1, 2, 3, 1), (1, 2, 3, 2)]
Now you have replaced each element of nodes list with a tuple (1,2,3,1). The is a complete replacement. It does not modify the sublists of nodes. So now nodes is a list of tuples.
In [119]: np.array(nodes)
Out[119]:
array([[1, 2, 3, 0],
[1, 2, 3, 1],
[1, 2, 3, 2]])
Passing that through np.array creates a 2d array, regardless of whether it is a list of lists or list of tuples.
If the sublists or tuples differ in length you'll get something else - a 1d array of dtype object.
You'll have to be more specific as to what you mean by array of arrays and associative array.