Reputation: 1017
Suppose I have the array:
[[2,1,5,2],
[1,4,2,1],
[4,5,5,7],
[1,5,9,3]]
I am trying to transpose the array to shape (16, 3) where the first two elements in the resulting array are the index numbers, and the last is the value. eg:
[[0, 0, 2], [1, 0, 1], [2, 0, 5], [3, 0, 2], [0, 1, 4], ....]
Is this possible with a numpy function or similar? Or I have to do this with my own function?
Working example code:
import numpy as np
src = np.array([[2,1,5,2],
[1,4,2,1],
[4,5,5,7],
[1,5,9,3]])
dst = np.array([])
for x in range(src.shape[0]):
for y in range(src.shape[1]):
dst = np.append(dst, [[y, x, src[x][y]]])
print(dst.reshape(16,3))
Upvotes: 1
Views: 252
Reputation: 43494
Update: There is a numpy function for that:
You can use numpy.ndenumerate
:
dst = np.array([[*reversed(x), y] for x, y in np.ndenumerate(src)])
print(dst)
#[[0 0 2]
# [1 0 1]
# [2 0 5]
# [3 0 2]
# [0 1 1]
# [1 1 4]
# [2 1 2]
# [3 1 1]
# [0 2 4]
# [1 2 5]
# [2 2 5]
# [3 2 7]
# [0 3 1]
# [1 3 5]
# [2 3 9]
# [3 3 3]]
ndenumerate
will return an iterator yielding pairs of array coordinates and values. You will first need to reverse the coordinates for your desired output. Next unpack the coordinates into a list1 with the value and use a list comprehension to consume the iterator.
Original Answer
You can try:
dst = np.column_stack(zip(*[*reversed(np.indices(src.shape)), src])).T
print(dst)
#[[0 0 2]
# [1 0 1]
# [2 0 5]
# [3 0 2]
# [0 1 1]
# [1 1 4]
# [2 1 2]
# [3 1 1]
# [0 2 4]
# [1 2 5]
# [2 2 5]
# [3 2 7]
# [0 3 1]
# [1 3 5]
# [2 3 9]
# [3 3 3]]
Explanation
First, use numpy.indices
to get an array representing the indices of a grid with the shape of src
.
print(np.indices(src.shape))
#[[[0 0 0 0]
# [1 1 1 1]
# [2 2 2 2]
# [3 3 3 3]]
#
# [[0 1 2 3]
# [0 1 2 3]
# [0 1 2 3]
# [0 1 2 3]]]
We can reverse these (since that's the order you want in your final output), and unpack into a list1 that also contains src
.
Then zip
all of the elements of this list to get the (col, row, val)
triples. We can stack these together using numpy.column_stack
.
list(zip(*[*reversed(np.indices(src.shape)), src]))
#[(array([0, 1, 2, 3]), array([0, 0, 0, 0]), array([2, 1, 5, 2])),
# (array([0, 1, 2, 3]), array([1, 1, 1, 1]), array([1, 4, 2, 1])),
# (array([0, 1, 2, 3]), array([2, 2, 2, 2]), array([4, 5, 5, 7])),
# (array([0, 1, 2, 3]), array([3, 3, 3, 3]), array([1, 5, 9, 3]))]
Finally transpose (numpy.ndarray.T
) to get the final output.
Notes:
list
is only available in python 3.5+Upvotes: 0
Reputation: 78
I don't know if there is a function in numpy for that, but you can use list comprehension to easily build that array:
import numpy as np
src = np.array([[2,1,5,2],
[1,4,2,1],
[4,5,5,7],
[1,5,9,3]])
dst = np.array([ [y, x, src[x][y]]
for x in range(src.shape[0])
for y in range(src.shape[1])])
print(dst.reshape(16,3))
Hope this can help.
Upvotes: 1