I have an example array:
>>> arr = np.array([[2, 4, 1], [3, 4, 2], [3, 6, 1]])
>>> arr
array([[2, 4, 1],
[3, 4, 2],
[3, 6, 1]])
Desired output:
array([[(0, 2), (1, 4), (2, 1)],
[(0, 3), (1, 4), (2, 2)],
[(0, 3), (1, 6), (2, 1)]])
I applied this:
np.apply_along_axis(lambda tuple(enumerate(x)), 1, arr)
I got different output:
array([[[0, 2],
[1, 4],
[2, 1]],
[[0, 3],
[1, 4],
[2, 2]],
[[0, 3],
[1, 6],
[2, 1]]])
CodePudding user response:
Usually you don't have tuples in a numpy array. Your output is basically what you desire but as lists and not as tuples. You can use a workaround like shown here:
import numpy as np
def return_tuple(x):
out = np.empty(len(x), dtype=object)
out[:] = list(enumerate(x))
return out
arr = np.array([[2,4,1],[3,4,2],[3,6,1]])
result = np.apply_along_axis(return_tuple, 1, arr)
print(result)
print(type(result))
[[(0, 2) (1, 4) (2, 1)]
[(0, 3) (1, 4) (2, 2)]
[(0, 3) (1, 6) (2, 1)]]
<class 'numpy.ndarray'>
CodePudding user response:
np.apply_along_axis
, np.vectorize
, and friends are not actually vectorized functions. The "undesired" output you show is what you get when you want to have a numerical array: you can index it the same as the array of tuples, and everything about it is better, except that it may not look as pretty. A faster way to make this array is
>>> np.stack((np.broadcast_to(np.arange(arr.shape[1]), arr.shape), arr), axis=-1)
array([[[0, 2],
[1, 4],
[2, 1]],
[[0, 3],
[1, 4],
[2, 2]],
[[0, 3],
[1, 6],
[2, 1]]])
Sure this looks wrong, but just get rid of a couple of newlines and you get
array([[[0, 2], [1, 4], [2, 1]],
[[0, 3], [1, 4], [2, 2]],
[[0, 3], [1, 6], [2, 1]]])
If you absolutely insist on having parenthes around your elements, you can do this without losing numpyness (i.e., contiguous blocks of numbers) by making a recarray with a custom dtype:
>>> result = np.empty_like(arr, dtype=[('i', int), ('x', arr.dtype)])
>>> result['x'] = arr
>>> result['i'] = np.arange(arr.shape[0])
And lo and behold, you get pretty parentheses:
array([[(0, 2), (1, 4), (2, 1)],
[(0, 3), (1, 4), (2, 2)],
[(0, 3), (1, 6), (2, 1)]], dtype=[('i', '<i4'), ('x', '<i4')])