Заполните нулевые значения массива 1d numpy с последними ненулевыми значениями

Предположим, у нас есть массив 1d numpy, заполненный некоторыми значениями int . И предположим, что некоторые из них равны 0 .

Есть ли способ, используя силу массива numpy , заполнить все значения 0 с последними ненулевыми значениями?

например:

 arr = np.array([1, 0, 0, 2, 0, 4, 6, 8, 0, 0, 0, 0, 2]) fill_zeros_with_last(arr) print arr [1 1 1 2 2 4 6 8 8 8 8 8 2] 

Способ сделать это будет с помощью этой функции:

 def fill_zeros_with_last(arr): last_val = None # I don't really care about the initial value for i in range(arr.size): if arr[i]: last_val = arr[i] elif last_val is not None: arr[i] = last_val 

Тем не менее, это использование scipy питона for цикла вместо того, чтобы использовать преимущества numpy и scipy .

Если бы мы знали, что возможно достаточно небольшое количество последовательных нулей, мы могли бы использовать что-то, основанное на numpy.roll . Проблема в том, что число последовательных нулей потенциально велико …

Есть идеи? или мы должны идти прямо к Cython ?

Отказ от ответственности:

Я бы сказал, что давным-давно я нашел вопрос в stackoverflow, задав что-то вроде этого или очень похоже. Я не смог его найти. 🙁

Возможно, я пропустил правильные условия поиска, извините за дубликат. Возможно, это было просто мое воображение …

3 Solutions collect form web for “Заполните нулевые значения массива 1d numpy с последними ненулевыми значениями”

Вот решение, использующее np.maximum.accumulate :

 def fill_zeros_with_last(arr): prev = np.arange(len(arr)) prev[arr == 0] = 0 prev = np.maximum.accumulate(prev) return arr[prev] 

Мы строим массив prev который имеет ту же длину, что и arr , и такой, что prev[i] является индексом последней ненулевой записи до i-й записи arr . Например, если:

 >>> arr = np.array([1, 0, 0, 2, 0, 4, 6, 8, 0, 0, 0, 0, 2]) 

Тогда prev выглядит так:

 array([ 0, 0, 0, 3, 3, 5, 6, 7, 7, 7, 7, 7, 12]) 

Затем мы просто индексируем в arr с prev и получаем наш результат. Тест:

 >>> arr = np.array([1, 0, 0, 2, 0, 4, 6, 8, 0, 0, 0, 0, 2]) >>> fill_zeros_with_last(arr) array([1, 1, 1, 2, 2, 4, 6, 8, 8, 8, 8, 8, 2]) 

Примечание . Будьте внимательны, чтобы понять, что это делает, когда первая запись вашего массива равна нулю:

 >>> fill_zeros_with_last(np.array([0,0,1,0,0])) array([0, 0, 1, 1, 1]) 

Вдохновленный ответом jme здесь и Bas Swinckels ' (в связанном вопросе), я придумал другую комбинацию функций numpy:

 def fill_zeros_with_last(arr, initial=0): ind = np.nonzero(arr)[0] cnt = np.cumsum(np.array(arr, dtype=bool)) return np.where(cnt, arr[ind[cnt-1]], initial) 

Я думаю, что это кратким и также работает, поэтому я размещаю его здесь для записи. Тем не менее, jme 's также лаконично и легко следовать и, кажется, быстрее, поэтому я принимаю его 🙂

Если 0 s входят только в строки 1, это использование nonzero может работать:

 In [266]: arr=np.array([1,0,2,3,0,4,0,5]) In [267]: I=np.nonzero(arr==0)[0] In [268]: arr[I] = arr[I-1] In [269]: arr Out[269]: array([1, 1, 2, 3, 3, 4, 4, 5]) 

Я могу обрабатывать ваш arr , применяя это повторно до тех пор, пока I станет пустым.

 In [286]: arr = np.array([1, 0, 0, 2, 0, 4, 6, 8, 0, 0, 0, 0, 2]) In [287]: while True: .....: I=np.nonzero(arr==0)[0] .....: if len(I)==0: break .....: arr[I] = arr[I-1] .....: In [288]: arr Out[288]: array([1, 1, 1, 2, 2, 4, 6, 8, 8, 8, 8, 8, 2]) 

Если строки из 0s длинны, может быть, лучше искать эти строки и обрабатывать их как блок. Но если большинство строк коротки, это повторяющееся приложение может быть самым быстрым путем.

  • Функция Python эквивалентна функции `pretty ()`?
  • Создание numpy linspace из даты и времени
  • Самый эффективный способ поиска режима в массиве numpy
  • Как сделать такой массив равенства быстрым (в numpy)?
  • Преобразование Pandas SparseDataframe в Scipy sparse csc_matrix
  • Установка порядка данных * по умолчанию * (C против Fortran) в Numpy
  • Написание более быстрого симулятора физики Python
  • как добавить матрицу numpy в пустой массив numpy
  • Python - лучший язык программирования в мире.