NumPy, принимая массив разницы их пересечения - PullRequest
0 голосов
/ 24 июня 2018

У меня есть несколько пустых массивов, и я хочу создать новые массивы, выполняющие что-то похожее на XOR ... но не совсем.

Мой ввод - два массива, array1 и array2.Мой вывод - модифицированная (или новый массив, мне все равно) версия array1.

Модификация выполняется поэлементно, выполняя следующие действия:

1.) Если какой-либо из массивов имеет0 для данного индекса, то индекс остается без изменений.2.) Если array1 и array2 отличны от нуля, то измененному массиву присваивается значение индекса array1, вычитаемое из индекса array2, до минимума, равного нулю.

Примеры:

array1:  [0, 3, 8, 0]
array2:  [1, 1, 1, 1]
output:  [0, 2, 7, 0]


array1:  [1, 1, 1, 1]
array2:  [0, 3, 8, 0]
output:  [1, 0, 0, 1]

array1:  [10, 10, 10, 10]
array2:  [8, 12, 8, 12]
output:  [2, 0, 2, 0]

Я хотел бы иметь возможность сделать это, скажем, с одним утверждением numpy.copyto, но я не знаю как.Спасибо.

edit:

это просто поразило меня.Могу ли я сделать:

new_array = np.zeros(size_of_array1)
numpy.copyto(new_array, array1-array2, where=array1>array2)

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

Хорошо, результаты представлены в виде:

массив случайных чисел от 0 до 5, размер = 10000, 10 циклов

1.)используя мой метод np.copyto

2.) используя клип

3.) используя максимум

0.000768184661865
0.000391960144043
0.000403165817261

Kasramvd также предоставил несколько полезных таймингов ниже

Ответы [ 3 ]

0 голосов
/ 24 июня 2018

Вы можете использовать простое вычитание и обрезать результат с нулем как min:

(arr1 - arr2).clip(min=0)

Демо-версия:

In [43]: arr1 = np.array([0,3,8,0]); arr2 = np.array([1,1,1,1])

In [44]: (arr1 - arr2).clip(min=0)
Out[44]: array([0, 2, 7, 0])

На больших массивах это также быстрее, чем maximum подход:

In [51]: arr1 = np.arange(10000); arr2 = np.arange(10000)

In [52]:  %timeit np.maximum(0, arr1 - arr2)
22.3 µs ± 1.77 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [53]: %timeit (arr1 - arr2).clip(min=0)
20.9 µs ± 167 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [54]: arr1 = np.arange(100000); arr2 = np.arange(100000)

In [55]:  %timeit np.maximum(0, arr1 - arr2)
671 µs ± 5.69 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [56]: %timeit (arr1 - arr2).clip(min=0)
648 µs ± 4.43 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Обратите внимание, что если arr2 может иметь отрицательные значения, вам следует рассмотреть возможность использования функции abs в arr2, чтобы получить ожидаемый результат:

(arr1 - abs(arr2)).clip(min=0)
0 голосов
/ 24 июня 2018

Вы можете сначала просто вычесть массивы, а затем использовать boolean array indexing для результата вычитания, чтобы присвоить 0, где есть отрицательные значения, как в:

# subtract
In [43]: subtracted = arr1 - arr2

# get a boolean mask by checking for < 0
# index into the array and assign 0
In [44]: subtracted[subtracted < 0] = 0

In [45]: subtracted
Out[45]: array([0, 2, 7, 0])

Применение того же для других входов, указанных в OP:

In [46]: arr1 = np.array([1, 1, 1, 1])
    ...: arr2 = np.array([0, 3, 8, 0])

In [47]: subtracted = arr1 - arr2
In [48]: subtracted[subtracted < 0] = 0

In [49]: subtracted
Out[49]: array([1, 0, 0, 1])

И для третьих входных массивов:

In [50]: arr1 = np.array([10, 10, 10, 10])
    ...: arr2 = np.array([8, 12, 8, 12])

In [51]: subtracted = arr1 - arr2
In [52]: subtracted[subtracted < 0] = 0

In [53]: subtracted
Out[53]: array([2, 0, 2, 0])
0 голосов
/ 24 июня 2018
In [73]: np.maximum(0,np.array([0,3,8,0])-np.array([1,1,1,1]))
Out[73]: array([0, 2, 7, 0])

Это явно не адрес

Если для любого массива указан 0 для индекса, индекс остается без изменений.

но результаты совпадают для всех примеров:

In [74]: np.maximum(0,np.array([1,1,1,1])-np.array([0,3,8,0]))
Out[74]: array([1, 0, 0, 1])
In [75]: np.maximum(0,np.array([10,10,10,10])-np.array([8,12,8,12]))
Out[75]: array([2, 0, 2, 0])
...