NumPy поменять несколько элементов в массиве - PullRequest
0 голосов
/ 20 ноября 2018

У меня есть массив NumPy, содержащий случайный разброс 1 и 0. Я хочу заменить все 1 на 0 и все нули на 1.

arr[arr == 0] = 2
arr[arr== 1] = 0
arr[arr== 2] = 1

В настоящее время мне нужно использовать временное значение (в данном случае 2), чтобы все 0 не становились 1, а затем впоследствии делали весь массив полным 0. Есть ли более элегантный / эффективный способ сделать это?

Ответы [ 5 ]

0 голосов
/ 21 ноября 2018

Если эффективное решение важнее элегантного, вы можете написать довольно простое Numba решение.

Пример

import numba as nb
import numpy as np

@nb.njit()
def nb_where(arr):
  for i in range(arr.shape[0]):
    for j in range(arr.shape[1]):
      if arr[i,j]==1:
        arr[i,j] = 0
      else:
        arr[i,j] = 1
  return arr

Задержка

a = np.eye(1000, dtype=int)
np.where(a == 0, 1, 0) #timgeb    -> 2.06ms 
a^1                    #Tls Chris -> 1.31ms 
nb_where(a)                       -> 152 µs
0 голосов
/ 20 ноября 2018

Для ваших конкретных значений побитового xor с 1.

In [19]: a=np.random.randint(2, size=10)

In [18]: a
Out[18]: array([1, 1, 1, 1, 1, 1, 0, 0, 1, 1])

In [19]: a^1
Out[19]: array([0, 0, 0, 0, 0, 0, 1, 1, 0, 0])

Более общее решение для типов int.

In [62]: convert=np.array([1,0])

In [63]: convert[a]
Out[63]: array([0, 0, 0, 0, 0, 0, 1, 1, 0, 0])

Изменение содержимого массива 'convert' означает, что диапазон значений может быть сопоставлен. Результат использует содержимое массива 'a' в качестве индекса в массиве 'convert'.

0 голосов
/ 20 ноября 2018

Вы можете вычислить и сохранить ваши логические индексаторы перед перезаписью любых значений:

ones = a == 1
zeros = a == 0

a[ones] = 0
a[zeros] = 1

Решение также работает, если у вас есть значения, отличные от 0 и 1.


Если вам не нужно решение на месте , вы можете использовать np.where:

a = np.where(ones, 0, np.where(zeros, 1, a))
0 голосов
/ 20 ноября 2018

Вот решение, которое очень специфично для вашей проблемы, но также должно быть очень быстрым. Учитывая массив:

>>> a
array([[1, 0, 0, 1],
       [1, 1, 1, 0]])

Вы можете вычесть 1 из всех значений и умножить на отрицательное 1:

>>> (a-1)*-1
array([[0, 1, 1, 0],
       [0, 0, 0, 1]])
0 голосов
/ 20 ноября 2018

Дано

>>> a
array([[1, 0, 0, 1],
       [1, 1, 1, 0]])

Вы можете использовать numpy.where

>>> np.where(a == 0, 1, 0) # read as (if, then, else)
array([[0, 1, 1, 0],
       [0, 0, 0, 1]])

... или, альтернативно, отрицаем a и выполняем некоторые типы.

>>> (~a.astype(bool)).astype(int)
array([[0, 1, 1, 0],
       [0, 0, 0, 1]])

(IPython) время: небольшая разница.

>>> a = np.eye(1000, dtype=int)
>>> %timeit np.where(a == 0, 1, 0)
1.56 ms ± 2.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
>>> %timeit (~a.astype(bool)).astype(int)
1.74 ms ± 87.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Время ответов других людей:

>>> %timeit a^1 # Tls Chris
920 µs ± 31.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
>>> %timeit np.array([1, 0])[a] # Tls Chris
1.4 ms ± 102 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
>>> %timeit (a - 1)*-1 # sacul
1.57 ms ± 13.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
>>> %timeit 1 - a # user3483203
905 µs ± 2.16 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Мое мнение: a^1 и 1 - a чистые, элегантные и быстрые. Использование np.where работает с любыми значениями, которые вы можете поменять местами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...