Reputation: 728
I have 2 numpy
arrays such as:
arr1 = np.array([[0,5,5,0],[0,5,5,0]])
arr2 = np.array([[7,7,0,0],[7,7,0,0]])
I'd like to copy non zero elements in arr2
into corresponding position in arr1
resulting the following array:
arr1 = np.array([[7,7,5,0],[7,7,5,0]])
Upvotes: 3
Views: 5551
Reputation: 5939
You can use three alternatives:
arr1[arr2 > 0] = arr2[arr2 > 0]
arr1[np.where(arr2>0)] = arr2[np.where(arr2>0)]
arr1[arr2.nonzero()] = arr2[arr2.nonzero()]
But a winner is np.copyto(arr1, arr2, where=arr2 != 0)
, thanks @Mark Meyer.
Every of these 4 methods changes arr1
into
array([[7, 7, 5, 0],
[7, 7, 5, 0]])
If you don't want side effects in arr1
, use arr = arr1.copy()
instead and ten replace it in analogous way.
Let's look at results of perfplot
import perfplot
def simple(arr):
arr1, arr2 = arr
arr1[arr2 != 0] = arr2[arr2 != 0]
return arr1
def where(arr):
arr1, arr2 = arr
arr1[np.where(arr2 != 0)] = arr2[np.where(arr2 != 0)]
return arr1
def nonzero(arr):
arr1, arr2 = arr
arr1[arr2.nonzero()] = arr2[arr2.nonzero()]
return arr1
def simple_improve(arr):
arr1, arr2 = arr
idx = arr2 != 0
arr1[idx] = arr2[idx]
return arr1
def where_improve(arr):
arr1, arr2 = arr
idx = np.where(arr2 != 0)
arr1[idx] = arr2[idx]
return arr1
def nonzero_improve(arr):
arr1, arr2 = arr
idx = arr2.nonzero()
arr1[idx] = arr2[idx]
return arr1
def copyto(arr): #thanks @Mark Meyer
arr1, arr2 = arr
np.copyto(arr1, arr2, where=arr2 != 0)
return arr1
import numexpr as ne
def copyto_numexpr(arr):
#some magic boost
arr1, arr2 = arr
np.copyto(arr1, arr2, where=ne.evaluate('arr2 != 0'))
return arr1
perfplot.show(
setup=lambda n: (np.tile(np.array([[0, 5, 5, 0], [0, 5, 5, 0]]), (n, n)),
np.tile(np.array([[7, 7, 0, 0], [7, 7, 0, 0]]), (n, n))),
# setup=lambda n: [list(range(n))] * 10,
kernels=[simple, where, nonzero,
simple_improve, where_improve, nonzero_improve,
copyto, copyto_numexpr],
n_range=[2 ** k for k in range(12)],
xlabel="n*n copies of array of shape (2,4)")
Upvotes: 9
Reputation: 92440
Since you want to mutate arr1
, you can just assign with boolean indexing:
import numpy as np
arr1 = np.array([[0,5,5,0],[0,5,5,0]])
arr2 = np.array([[7,7,0,0],[7,7,0,0]])
arr1[arr2 != 0] = arr2[arr2 != 0]
print(arr1)
# [[7 7 5 0]
# [7 7 5 0]]
You can pick up a little performance on large arrays using copyto()
:
np.copyto(arr1, arr2, where=arr2 != 0)
Upvotes: 3