Suppose I have an array contains index [2,1,1,2,0], I would like to create a new array 3x5 that only has value equal to 1 at index 2 for first row, at index 1 for second row, and so on..
For example:
[[0, 0, 1], #2
[0, 1, 0], #1
[0, 1, 0], #1
[0, 0, 1], #2
[1, 0, 0]] #0
How could I vectorize this procedure without using for loop?
import numpy as np
in_index = [2,1,1,2,0]
len_in_index = len(in_index)
result = np.zeros((len_in_index, 3), dtype=int)
for i in range(len_in_index):
result[i, in_index[i]] = 1
print(result)
Output:
[[0 0 1]
[0 1 0]
[0 1 0]
[0 0 1]
[1 0 0]]
Related
I'm trying to replace values in specific columns with zero with python, and the column numbers are specified in another array.
Given the following 2 numpy arrays
a = np.array([[ 1, 2, 3, 4],
[ 1, 2, 1, 2],
[ 0, 3, 2, 2]])
and
b = np.array([1,3])
b indicates column numbers in array "a" where values need to be replaced with zero.
So the expected output is
([[ 1, 0, 3, 0],
[ 1, 0, 1, 0],
[ 0, 0, 2, 0]])
Any ideas on how I can accomplish this? Thanks.
Your question is:
I'm trying to replace values in specific columns with zero with python, and the column numbers are specified in another array.
This can be done like this:
a[:,b] = 0
Output:
[[1 0 3 0]
[1 0 1 0]
[0 0 2 0]]
The Integer array indexing section of Indexing on ndarrays in the numpy docs has some similar examples.
A simple for loop will accomplish this.
for column in b:
for row in range(len(a)):
a[row][column] = 0
print(a)
[[1 0 3 0]
[1 0 1 0]
[0 0 2 0]]
I am a beginner, and I want to know is it possible to convert a boolean array into a matrix in NumPy?
For example, we have a boolean array a like this:
a = [[False],
[True],
[True],
[False],
[True]]
And, we turn it into the following matrix:
m = [[0, 0, 0, 0, 0]
[0, 1, 0, 0, 0]
[0, 0, 1, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 1]]
I mean the array to be the diagonal of the matrix.
You can use np.diagflat which creates a two-dimensional array with the flattened input as a diagonal:
np.diagflat(np.array(a, dtype=int))
#[[0 0 0 0 0]
# [0 1 0 0 0]
# [0 0 1 0 0]
# [0 0 0 0 0]
# [0 0 0 0 1]]
Working example
Example
[ 0 0 1,
1 0 1,
0 1 0 ]
Returned postions: (1,3) ,(2,1) ,(2,3),(3,2)
You can use numpy:
import numpy as np
x=np.array([ [0, 0, 1], [1, 0, 1], [0, 1 ,0 ]])
res=np.argwhere(x==1)
print(x,res, sep="\n")
Outputs:
[[0 0 1]
[1 0 1]
[0 1 0]]
[[0 2]
[1 0]
[1 2]
[2 1]]
Some useful reference:
https://docs.scipy.org/doc/numpy/reference/generated/numpy.argwhere.html
Suppose I have an array
[[0 2 1]
[1 0 1]
[2 1 1]]
and I want to convert it into a tensor of the form
[[[1 0 0]
[0 1 0]
[0 0 0]]
[[0 0 1]
[1 0 1]
[0 1 1]]
[[0 1 0]
[0 0 0]
[1 0 0]]]
Where each depth layer (index i) is a binary mask showing where i appears in the input.
I have written code for this which works correctly but is too slow for any use. Can I replace the loop in this function with another vectorized operation?
def im2segmap(im, depth):
tensor = np.zeros((im.shape[0], im.shape[1], num_classes))
for c in range(depth):
rows, cols = np.argwhere(im==c).T
tensor[c, rows, cols] = 1
return tensor
Use broadcasting -
(a==np.arange(num_classes)[:,None,None]).astype(int)
Or with builtin outer comparison -
(np.equal.outer(range(num_classes),a)).astype(int)
Use uint8 if you have to use an int dtype or keep as boolean by skipping the int conversion altogether for further boost.
Sample run -
In [42]: a = np.array([[0,2,1],[1,0,1],[2,1,1]])
In [43]: num_classes = 3 # or depth
In [44]: (a==np.arange(num_classes)[:,None,None]).astype(int)
Out[44]:
array([[[1, 0, 0],
[0, 1, 0],
[0, 0, 0]],
[[0, 0, 1],
[1, 0, 1],
[0, 1, 1]],
[[0, 1, 0],
[0, 0, 0],
[1, 0, 0]]])
To have the depth/num_classes as the third dim, extend the input array and then compare against the range array -
(a[...,None]==np.arange(num_classes)).astype(int)
(np.equal.outer(im, range(num_classes))).astype(int)
(np.equal.outer(im, range(num_classes))).astype(np.uint8) # lower prec
I'm interested in finding out individual sizes of the 'True' patches in a boolean array. For instance in the boolean matrix:
[[1, 0, 0, 0],
[0, 1, 1, 0],
[0, 1, 0, 0],
[0, 1, 0, 0]]
The output would be:
[[1, 0, 0, 0],
[0, 4, 4, 0],
[0, 4, 0, 0],
[0, 4, 0, 0]]
I'm aware that I can do this recursively, but I'm also under the impression that python array operations are costly on large scale and is there an available library function for this?
Here's a quick and simple complete solution:
import numpy as np
import scipy.ndimage.measurements as mnts
A = np.array([
[1, 0, 0, 0],
[0, 1, 1, 0],
[0, 1, 0, 0],
[0, 1, 0, 0]
])
# labeled is a version of A with labeled clusters:
#
# [[1 0 0 0]
# [0 2 2 0]
# [0 2 0 0]
# [0 2 0 0]]
#
# clusters holds the number of different clusters: 2
labeled, clusters = mnts.label(A)
# sizes is an array of cluster sizes: [0, 1, 4]
sizes = mnts.sum(A, labeled, index=range(clusters + 1))
# mnts.sum always outputs a float array, so we'll convert sizes to int
sizes = sizes.astype(int)
# get an array with the same shape as labeled and the
# appropriate values from sizes by indexing one array
# with the other. See the `numpy` indexing docs for details
labeledBySize = sizes[labeled]
print(labeledBySize)
output:
[[1 0 0 0]
[0 4 4 0]
[0 4 0 0]
[0 4 0 0]]
The trickiest line above is the "fancy" numpy indexing:
labeledBySize = sizes[labeled]
in which one array is used to index the other. See the numpy indexing docs (section "Index arrays") for details on why this works.
I also wrote a version of the above code as a single compact function that you can try out yourself online. It includes a test case based on a random array.