Using np.multiply(out=array[mask]) does not work
Question:
I tested the behavior of in-place operations with numpy. I observed the following:
test = np.arange(0, 10).reshape(2, 5)
mask = test > 5
This works
np.multiply(test, 3, out=test)
# Output:
[[ 0 3 6 9 12]
[15 18 21 24 27]]
but this
np.multiply(test[mask], 3, out=test[mask])
print(test)
# Output:
[[0 1 2 3 4]
[5 6 7 8 9]]
doesn’t. Why?
Answers:
Here are some tests for comparison sake:
With few Truthy values in the mask:
import numpy as np
test = np.arange(100000)
mask = test < 100
%timeit np.multiply(test, 3, out=test, where=mask)
# 6.98 µs ± 90.2 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
%timeit test[mask] *= 3
# 21.3 µs ± 159 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
%timeit test[mask] = test[mask] * 3
# 21.9 µs ± 214 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
with a lot of Truthy values:
test = np.arange(100000)
mask = test < 90000
%timeit np.multiply(test, 3, out=test, where=mask)
# 60.9 µs ± 554 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit test[mask] *= 3
# 100 µs ± 474 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit test[mask] = test[mask] * 3
# 120 µs ± 1.09 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
with random mask:
test = np.arange(100000)
mask = np.random.choice([True, False], size=100000)
%timeit np.multiply(test, 3, out=test, where=mask)
# 411 µs ± 4.25 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%timeit test[mask] *= 3
# 712 µs ± 7.93 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%timeit test[mask] = test[mask] * 3
# 714 µs ± 5.72 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
for completeness, without a mask:
%timeit np.multiply(test, 3, out=test)
# 22.4 µs ± 126 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
so I would recommend np.multiply
with out=arr
and where=mask
.
I tested the behavior of in-place operations with numpy. I observed the following:
test = np.arange(0, 10).reshape(2, 5)
mask = test > 5
This works
np.multiply(test, 3, out=test)
# Output:
[[ 0 3 6 9 12]
[15 18 21 24 27]]
but this
np.multiply(test[mask], 3, out=test[mask])
print(test)
# Output:
[[0 1 2 3 4]
[5 6 7 8 9]]
doesn’t. Why?
Here are some tests for comparison sake:
With few Truthy values in the mask:
import numpy as np
test = np.arange(100000)
mask = test < 100
%timeit np.multiply(test, 3, out=test, where=mask)
# 6.98 µs ± 90.2 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
%timeit test[mask] *= 3
# 21.3 µs ± 159 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
%timeit test[mask] = test[mask] * 3
# 21.9 µs ± 214 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
with a lot of Truthy values:
test = np.arange(100000)
mask = test < 90000
%timeit np.multiply(test, 3, out=test, where=mask)
# 60.9 µs ± 554 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit test[mask] *= 3
# 100 µs ± 474 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit test[mask] = test[mask] * 3
# 120 µs ± 1.09 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
with random mask:
test = np.arange(100000)
mask = np.random.choice([True, False], size=100000)
%timeit np.multiply(test, 3, out=test, where=mask)
# 411 µs ± 4.25 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%timeit test[mask] *= 3
# 712 µs ± 7.93 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%timeit test[mask] = test[mask] * 3
# 714 µs ± 5.72 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
for completeness, without a mask:
%timeit np.multiply(test, 3, out=test)
# 22.4 µs ± 126 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
so I would recommend np.multiply
with out=arr
and where=mask
.