Say a
is a numpy array of shape (N,)
and b = a[k:l]
. I know that x = b[i]
, is there a way to find j
such that x = a[j]
without knowing k
and l
and without searching a
for x
?
For instance a = np.array([2,4,3,1,7])
and b = a[1:4]
. I only have access to b
, but would like to know what the index of 3
is in a
, knowing that its index in b
is 1
.
Of course I could access a
by using b.base
, and then search a
for the item 3
, but I wondered wether there is a method attached to views which returns the index of an item in the base array.
CodePudding user response:
As @hpaulj already has stated in the comments, there is no built in functionality to do so. But you can still compute the base's index from the size of the dtype
and the byte offset between the base and the view. You can obtain the byte offset from the attribute ndarray.__array_interface__['data'][0]
import numpy as np
import unittest
def baseIndex(array: np.ndarray, index: int) -> int:
base = array.base
if base is None:
return index
size = array.dtype.itemsize
stride = array.strides[0] // size
offset = (array.__array_interface__['data'][0] - base.__array_interface__['data'][0]) // size
return offset index * stride
a = np.array([0,1,2,3,4,5,6])
b = a
class Test(unittest.TestCase):
def test_1_simple(self):
"""b = a"""
b = a
i = 1
j = baseIndex(b, i)
self.assertEqual(a[j], b[i])
def test_2_offset(self):
"""b = a[3:]"""
b = a[3:]
i = 1
j = baseIndex(b, i)
self.assertEqual(a[j], b[i])
def test_3_strided(self):
"""b = a[1::2]"""
b = a[1::2]
i = 1
j = baseIndex(b, i)
self.assertEqual(a[j], b[i])
def test_4_reverse_strided(self):
"""b = a[4::-2]"""
b = a[4::-2]
i = 1
j = baseIndex(b, i)
self.assertEqual(a[j], b[i])
unittest.main(verbosity=2)
Output:
test_1_simple (__main__.Test)
b = a ... ok
test_2_offset (__main__.Test)
b = a[3:] ... ok
test_3_strided (__main__.Test)
b = a[1::2] ... ok
test_4_reverse_strided (__main__.Test)
b = a[4::-2] ... ok
----------------------------------------------------------------------
Ran 4 tests in 0.001s
OK
EDIT: I have now updated the function to handle cases where b
is non-contiguous and/or reverse, thanks @Jérôme Richard for spotting that. Also, as @mozway states, ndarray.__array_interface__
is an internal numpy detail that can change without notice, but as of now I don't see any other way to do so.