假设我有
>>> v
array([1, 1, 1, 1, 1, 2, 2, 2, 3, 4, 3, 4, 3, 4, 3, 4, 5, 5, 5])
是否有一种有效的numpy方法来查找值变化的每个索引?例如,我想要一些结果,如
>>> index_of_changed_values(v)
[0, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16]
如果使用一些numpy例程是不可能的,那么在python中执行此操作的快速方法是什么?由于我是一个初学者,所以我可以参考一些好的numpy教程。
答案 0 :(得分:42)
您可以通过将每个元素与其邻居进行比较来获得numpy中的此功能;
v[:-1] != v[1:]
array([False, False, False, False, True, False, False, True, True,
True, True, True, True, True, True, True, False, False], dtype=bool)
获取您使用“where”函数的索引
np.where(v[:-1] != v[1:])[0]
array([ 4, 7, 8, 9, 10, 11, 12, 13, 14, 15])
从这里你可以添加第一个元素并添加一个元素以获得你问题中的相同索引方案。
答案 1 :(得分:4)
将近十年后,但我今天遇到了这个。
@kith 的回答很好,但可能没有我们想要的那么简洁(还要考虑到答案中没有明确的步骤)。
完整形式的答案是,
v = np.array([1, 1, 1, 1, 1, 2, 2, 2, 3, 4, 3, 4, 3, 4, 3, 4, 5, 5, 5])
np.concatenate((np.array([0]),np.where(v[:-1] != v[1:])[0]+1),axis=0)
我更喜欢的另一种选择是,
np.where(np.diff(v,prepend=np.nan))[0]
也返回
array([ 0, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16], dtype=int64)
正如我所说,这个想法与@kith 的想法相同,但是,
v[:-1] != v[1:]
替换为 np.diff()
,然后在 np.where
中将数组强制转换为布尔值,这没有太大变化,但看起来更整洁。np.nan
之前预置 np.diff()
来完成的。 diff 输出的第一个元素将是 np.nan
,并且在 python np.nan 中总是计算 True
。答案 2 :(得分:1)
与@kith回答相似,但需要较少的按摩结果:
np.where(np.roll(v,1)!=v)[0]
无需添加0或添加1。 例如:
>>> v=np.array([1, 1, 1, 2, 2, 3, 3, 4, 4, 4])
>>> np.where(np.roll(v,1)!=v)[0]
array([0, 3, 5, 7])
编辑:正如@Praveen所提到的,当最后一个和第一个元素相等时,这会失败。
答案 3 :(得分:-2)
也许它是因为Python 3.5,但上面的代码对我不起作用。
看起来v[:-1] != v[1:]
不会返回iterable
而只返回bool
。
我使用zip
和enumerate
[ i for i, (x, y) in enumerate(zip(v[:-1],v[1:])) if x!=y]
有人在py3.5中寻找解决方案可能会觉得这很有用!