Create new array based on the value and shapes of current array - python

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

Python How to replace values in specific columns (defined by an array) with zero

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]]

How to convert a boolean array into a matrix?

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

What is the best way to find postion (i, j) of 1's in matrix of zeros and ones?

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

Speed up numpy integer-array indexing for depth

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

numpy 2d boolean array count consecutive True sizes

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.

Categories

Resources