Вырезание массива на основе индекса - PullRequest
0 голосов
/ 01 мая 2018

У меня есть массив 1D numpy. Разница между двумя последующими значениями в этом массиве равна одному или больше единицы. Я хочу разрезать массив на части для каждого случая, когда разница больше единицы. Следовательно:

arr = numpy.array([77, 78, 79, 80, 90, 91, 92, 100, 101, 102, 103, 104])

должно стать

[array([77, 78, 79, 80]), array([90, 91, 92]), array([100, 101, 102, 103, 104])]

У меня есть следующий код, который справляется с задачей, но у меня такое ощущение, что мне здесь сложно. Должен быть лучший / более питонический способ. Кто-нибудь с более элегантным подходом?

import numpy

def split(arr, cut_idxs):

  empty_arr = []
  for idx in range(-1, cut_idxs.shape[0]):  
    if idx == -1:
      l, r = 0, cut_idxs[0]
    elif (idx != -1) and (idx != cut_idxs.shape[0] - 1):
      l, r = cut_idxs[idx] + 1, cut_idxs[idx + 1]
    elif idx == cut_idxs.shape[0] - 1:
      l, r = cut_idxs[-1] + 1, arr.shape[0]

    empty_arr.append(arr[l:r + 1]) 

  return empty_arr 


arr = numpy.array([77, 78, 79, 80, 90, 91, 92, 100, 101, 102, 103, 104])
cuts = numpy.where(numpy.ediff1d(arr) > 2)[0]

print split(arr, cuts)

Ответы [ 2 ]

0 голосов
/ 01 мая 2018

Другой способ нарезки, получение соответствующих индексов с помощью np.diff:

import numpy as np
def split(arr):
    idx = np.pad(np.where(np.diff(arr) > 1)[0]+1, (1,1),
             'constant', constant_values = (0, len(arr)))
    return [arr[idx[i]: idx[i+1]] for i in range(len(idx)-1)]

Результат:

arr = np.array([77, 78, 79, 80, 90, 91, 92, 100, 101, 102, 103, 104])
>>> split(arr)
[array([77, 78, 79, 80]), array([90, 91, 92]), array([100, 101, 102, 103, 104])]

В вашем случае ваша "карта" нарезки idx заканчивается: array([ 0, 4, 7, 12]), где diff больше 1 (индексы 4 и 7), дополненные нулями на слева и длина вашего массива (12) справа, используя np.pad

Но np.split, как подсказывает @Divakar, похоже, путь

0 голосов
/ 01 мая 2018

Один Pythonic путь будет -

np.split(arr, np.flatnonzero(np.diff(arr)>1)+1)

Пробный прогон -

In [10]: arr
Out[10]: array([ 77,  78,  79,  80,  90,  91,  92, 100, 101, 102, 103, 104])

In [11]: np.split(arr, np.flatnonzero(np.diff(arr)>1)+1)
Out[11]: 
[array([77, 78, 79, 80]),
 array([90, 91, 92]),
 array([100, 101, 102, 103, 104])]

Другой с slicing -

In [16]: cut_idx = np.r_[0,np.flatnonzero(np.diff(arr)>1)+1,len(arr)]
             # Or np.flatnonzero(np.r_[True, np.diff(arr)>1, True])

In [17]: [arr[i:j] for i,j in zip(cut_idx[:-1],cut_idx[1:])]
Out[17]: 
[array([77, 78, 79, 80]),
 array([90, 91, 92]),
 array([100, 101, 102, 103, 104])]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...