Numpy combine all nonzero elements of one array in to another - python

In Numpy I have two three dimensional arrays representing images. I'm trying to create an overlay of the second image on to first so I'd like to replace all of the elements in the first array with respective elements from the second array but only when they aren't zero. Is there any easy way to do this?

This seems like a perfect use-case for np.where ...
new_arr = np.where(second == 0, first, second)
I've done the replacement out-of-place (creating a new array rather than modifying the original), but that's usually OK...

You can simply do:
zeros_idx = array2 != 0
array1[zeros_idx] = array2[zeros_idx]

Modifying the original using numpy.nonzero. Similar to answer provided by #Holt .
m = numpy.nonzero(array2)
array1[m] = array2[m]

Related

Getting a single array containing several sub-arrays iteratively

I have a little question about python Numpy. What I want to do is the following:
having two numpy arrays arr1 = [1,2,3] and arr2 = [3,4,5] I would like to obtain a new array arr3 = [[1,2,3],[3,4,5]], but in an iterative way. For a single instance, this is just obtained by typing arr3 = np.array([arr1,arr2]).
What I have instead, are several arrays e.g. [4,3,1 ..], [4,3,5, ...],[1,2,1,...] and I would like to end up with [[4,3,1 ..], [4,3,5, ...],[1,2,1,...]], potentally using a for loop. How should I do this?
EDIT:
Ok I'm trying to add more details to the overall problem. First, I have a list of strings list_strings=['A', 'B','C', 'D', ...]. I'm using a specific method to obtain informative numbers out of a single string, so for example I have method(list_strings[0]) = [1,2,3,...], and I can do this for each single string I have in the initial list.
What I would like to come up with is an iterative for loop to end up having all the numbers extracted from each string in turn in the way I've described at the beginning, i.e.a single array with all the numeric sub-arrays with information extracted from each string. Hope this makes more sense now, and sorry If I haven't explained correctly, I'm really new in programming and trying to figure out stuff.
Well if your strings are in a list, we want to put the arrays that result from calling method in a list as well. Python's list comprehension is a great way to achieve that.
list_strings = ['A', ...]
list_of_converted_strings = [method(item) for item in list_strings]
arr = np.array(list_of_converted_strings)
Numpy arrays are of fixed dimension i.e. for example a 2D numpy array of shape n X m will have n rows and m columns. If you want to convert a list of lists into a numpy array all the the sublists in the main list should be of same length. You cannot convert it into a numpy array if sublist are of varying size.
For example, below code will give an error
np.array([[1], [3,4]]])
so if all the sublist are of same size then you can use
np.array([method(x) for x in strings]])

How to add dimension to array to create an image in Python

I have converted an image into a 2-dim Array to make some analysis:
im=imageio.imread(file)
im2D=im[:,:,0]
Now I need an efficient way to turn over this step. For the moment I'm doing this with 2 for-loops but I think this is really inefficient:
NewImage=np.zeros((len(im2D),len(im2D[0]),3,dtype=int)
for x in range(len(im2D)):
for y in range(len(im2D[0])):
NewImage[x][y]=[im2D[x][y],im2D[y][y],im2D[x][y]]
NewImage=NewImage.astype(np.uint8)
Example:
imageio gives me something like this:
im=Array([[[255,255,255,255],
...
[255,255,255,255]],
[ 0, 0, 0, 0],
...
[255,255,255,255]]],dtype=uint8)
and im[:,:,0] gives me something like this:
im2D=Array([[255,...,255],
...
[ 0,...,255]],dtype=uint8)
Assuming that I understand your question correctly and your goal is to add a dimension (an additional axis) to your existing array in which you repeat the existing data three times.
Then you could use one of the following ways:
# the 2d array
arr = np.ones((5,5))
# a manually way to stack the array 3 times along a new axis
arr3d1 = np.array([arr for i in range(3)])
# even more manually (without stacked loops though)
# useful if you want to change the content eg:
arr3d2 = np.array([arr, 1/arr, 2*arr])
# use numpy's tile
arr_h=arr[None,:,:] # first prepend a new singular axis
arr3d3 = np.tile(arr_h, (3,1,1)) # repeat 3 times along first axis and keep other axes
I think I have already found a solution to avoid the for-loops:
D3->D2:
im=imageio.imread(file)
im2D=im[:,:,0]
2D->D3:
NewImage=np.zeros((len(im2D),len(im2D[0]),3,dtype=int)
NewImage[:,:,0]=im2D
NewImage[:,:,1]=im2D
NewImage[:,:,2]=im2D

How do you print out elements from a Numpy array on new lines using a for loop?

Create an array with numpy and add elements to it. After you do this, print out all its elements on new lines.
I used the reshape function instead of a for loop. However, I know this would create problems in the long run if I changed my array values.
import numpy as np
a = np.array([0,5,69,5,1])
print(a.reshape(5,1))
How can I make this better? I think a for loop would be best in the long run but how would I implement it?
Some options to print an array "vertically" are:
print(a.reshape(-1, 1)) - You can pass -1 as one dimension,
meaning "expand this dimension to the needed extent".
print(np.expand_dims(a, axis=1)) - Add an extra dimension, at the second place,
so that each row will have a single item. Then print.
print(a[:, None]) - Yet another way of reshaping the array.
Or if you want to print just elements of a 1-D array in a column,
without any surrounding brackets, run just:
for x in a:
print(x)
You could do this:
print(a.reshape([a.shape[0], 1]))
This will work regardless of how many numbers are in your numpy array.
Alternatively, you could also do this:
[print(number) for number in a.tolist()]

Numpy array of multiple indices replace with a different matrix

I have an array of 2d indices.
indices = [[2,4], [6,77], [102,554]]
Now, I have a different 4-dimensional array, arr, and I want to only extract an array (it is an array, since it is 4-dimensional) with corresponding index in the indices array. It is equivalent to the following code.
for i in range(len(indices)):
output[i] = arr[indices[i][0], indices[i][1]]
However, I realized that using explicit for-loop yields a slow result. Is there any built-in numpy API that I can utilized? At this point, I tried using np.choose, np.put, np.take, but did not succeed to yield what I wanted. Thank you!
We need to index into the first two axes with the two columns from indices (thinking of it as an array).
Thus, simply convert to array and index, like so -
indices_arr = np.array(indices)
out = arr[indices_arr[:,0], indices_arr[:,1]]
Or we could extract those directly without converting to array and then index -
d0,d1 = [i[0] for i in indices], [i[1] for i in indices]
out = arr[d0,d1]
Another way to extract the elements would be with conversion to tuple, like so -
out = arr[tuple(indices_arr.T)]
If indices is already an array, skip the conversion process and use indices in places where we had indices_arr.
Try using the take function of numpy arrays. Your code should be something like:
outputarray= np.take(arr,indices)

2D python list of numpy arrays to 2D numpy array

Which is the most performant way
to convert something like that
problem = [ [np.array([1,2,3]), np.array([4,5])],
[np.array([6,7,8]), np.array([9,10])]]
into
desired = np.array([[1,2,3,4,5],
[6,7,8,9,10]])
Unfortunately, the final number of columns and rows (and length of subarrays) is not known in advance, as the subarrays are read from a binary file, record by record.
How about this:
problem = [[np.array([1,2,3]), np.array([4,5])],
[np.array([6,7,8]), np.array([9,10])]]
print np.array([np.concatenate(x) for x in problem])
I think this:
print np.array([np.hstack(i) for i in problem])
Using your example, this runs in 0.00022s, wherease concatenate takes 0.00038s
You can also use apply_along_axis although this runs in 0.00024s:
print np.apply_along_axis(np.hstack, 1, problem)

Categories

Resources