numpy数组中的值组除以N个连续K个值的索引

4sup72z8  于 2023-08-05  发布在  其他
关注(0)|答案(1)|浏览(112)

假设我有一个这样的数组:

  1. numpy.array([0, 0, 1, 2, 3, 0, 0, 4, 5, 0, 0, 0, 0, 1, 0, 6, 0, 7, 8, 9, 0, 0, 0, 8, 10, 0])

字符串
定义一个长度(N)和一个值(K),我想确定一系列的值(包括零),这些值被彼此除以至少N个连续的K,每个块的开始和停止索引。
因此,与:

  1. N = 2
  2. K = 0


我们最终将得到:

  1. #blocks
  2. [ [1, 2, 3], [4, 5], [1, 0, 6, 0, 7, 8, 9], [8, 10] ]
  1. #indexes
  2. [ [2, 4], [7, 8], [13, 19], [23, 24] ]

的字符串
在该示例中,块3(索引为2)还包含0,即所选择的K值,因为没有足够的连续出现(至少N个)来标识两个独立块。
实现这种避免循环的最聪明的方法是什么?
现在我采用了这种方法:

  1. def consecutive_blocks(arr,K,N):
  2. d = numpy.diff(numpy.concatenate(([False], arr==K, [False])).astype(int))
  3. idx_i = numpy.flatnonzero(d == -1)[:-1]
  4. idx_j = numpy.flatnonzero(d == 1)[1:] - 1
  5. delta = numpy.flatnonzero(d == -1) - numpy.flatnonzero(d == 1)
  6. idx_ii = idx_i[numpy.where(delta >= N)[0]]
  7. return idx_ii


这样我就得到了块的起始索引,但是我还需要进一步的工作来得到结束索引。

mwg9r5ms

mwg9r5ms1#

这里有一个方法:

  1. import numpy as np
  2. A = np.array([0, 0, 1, 2, 3, 0, 0, 4, 5, 0, 0, 0, 0, 1, 0, 6, 0, 7, 8,
  3. 9, 0, 0, 0, 8, 10, 0])
  4. N = 2
  5. K = 0
  6. b = np.tile(A,N+1)[:N*(A.size+1)].reshape((N,A.size+1)).T
  7. c = np.where(np.all(b[:A.size-N+1]==[K]*N,axis=1))[0]
  8. c = np.concatenate(([-N],c,[A.size]))
  9. d = np.stack((c[:-1]+N,c[1:]-1)).T
  10. e = d[d[:,0]<=d[:,1]]
  11. print(e)
  12. [[ 2 4]
  13. [ 7 8]
  14. [13 19]
  15. [23 25]] # last zero included (doesn't form a [0,0])

字符串

  • b创建一个2D矩阵,其中每行对应于长度为N的值的滚动子范围。
  • c查找与K重复N次模式匹配的行的索引。这给出了[0,0]子范围的起始位置。添加表示数组开始和结束的索引以完成边缘范围。
  • d将每个起始位置与下一个起始位置组合以形成索引范围。开始索引增加N以获得第一个非K值,并且接下来的开始减少1以获得组中最后一个项目的索引。
  • e消除了由多于N个连续K值的序列引起的“空”范围。

根据下面的注解,可以通过更改前两行来利用as_stridedsliding_window_view(* 我只能测试as_strided*)来获得更好的性能:

  1. b = np.lib.stride_tricks.as_strided(A, shape=(len(A)-N+1,N),
  2. strides=A.strides*2)
  3. c = np.where(np.all(b==[K]*N,axis=1))[0]


中间值:

  1. # b[:A.size-N+1] : rolling subranges of length N
  2. array([[ 0, 0],
  3. [ 0, 1],
  4. [ 1, 2],
  5. [ 2, 3],
  6. [ 3, 0],
  7. [ 0, 0],
  8. [ 0, 4],
  9. [ 4, 5],
  10. [ 5, 0],
  11. [ 0, 0],
  12. [ 0, 0],
  13. [ 0, 0],
  14. [ 0, 1],
  15. [ 1, 0],
  16. [ 0, 6],
  17. [ 6, 0],
  18. [ 0, 7],
  19. [ 7, 8],
  20. [ 8, 9],
  21. [ 9, 0],
  22. [ 0, 0],
  23. [ 0, 0],
  24. [ 0, 8],
  25. [ 8, 10],
  26. [10, 0]])


...

  1. # c : starting index of [K]*N patterns (and edges)
  2. array([-2, 0, 5, 9, 10, 11, 20, 21, 25, 26])


...

  1. # d : subranges between [K]*N patterns (including empties)
  2. array([[ 0, -1],
  3. [ 2, 4],
  4. [ 7, 8],
  5. [11, 9],
  6. [12, 10],
  7. [13, 19],
  8. [22, 20],
  9. [23, 25]])

展开查看全部

相关问题