Keep First Non-Zero Element, Set All Others to 0 - python

I have a 2-d NumPy array that looks like this:
array([[0. , 0. , 0.2, 0.2],
[0.3, 0. , 0.3, 0. ]])
I'd like to modify it so that each row consists of all 0's, except for the first non-zero entry. If it's all 0s to start with, we don't change anything.
I could do this:
example = np.array([[0,0, 0.2, 0.2], [0.3, 0, 0.3, 0]])
my_copy = np.zeros_like(example)
for i, row in enumerate(example):
for j, elem in enumerate(row):
if elem > 0:
my_copy[i, j] = elem
break
But that's ugly and not vectorized. Any suggestions for how to vectorize this?
Thanks!

Here's a vectorised solution. The trick is to calculate your first non-zero entries via bool conversion and argmax.
import numpy as np
A = np.array([[0. , 0. , 0.2, 0.2],
[0.3, 0. , 0.3, 0. ],
[0. , 0. , 0. , 0. ]])
res = np.zeros(A.shape)
idx = np.arange(res.shape[0])
args = A.astype(bool).argmax(1)
res[idx, args] = A[idx, args]
print(res)
array([[ 0. , 0. , 0.2, 0. ],
[ 0.3, 0. , 0. , 0. ],
[ 0. , 0. , 0. , 0. ]])

Simply
e =np.zeros(example.shape)
rows = np.arange(example.shape[0])
cols = np.argmax(example != 0, 1)
e[rows, cols] = example[rows, cols]

Setup
x = np.array([[0. , 0. , 0.2, 0.2],
[0.3, 0. , 0.3, 0. ],
[0. , 0. , 0. , 0. ]])
Using logical_and with np.eye:
m = (x!=0).argmax(1)
x[~np.logical_and(x, np.eye(x.shape[1])[m])] = 0
Output:
array([[0. , 0. , 0.2, 0. ],
[0.3, 0. , 0. , 0. ],
[0. , 0. , 0. , 0. ]])
Using this method will be slightly slower than the other two suggested.

Related

how to supress very small scientific notations to zero?

In sub-list of b the numbers are very close to zero , i wanted to make it equal to zeros if, they are >-1e-05.
is there is any better method ?
b = [[0.0, -2.220446049250313e-16, -8.881784197001252e-16, -6.661338147750939e-16, 0.0],
[0.0, -0.1875000, -0.1250000, -0.0625000, 0.0],
[0.0, -0.125000, -0.25000, -0.1250, 0.0],
[0.0, -0.06250, -0.1250, -0.18750, 0.0], [0, 0, 0, 0, 0]]
for i in b:
for j in i:
if j > -1e-05:
j = 0
else:
j = j
To do this, you can use numpy and np.where. First transform your list into an array:
import numpy as np
b = np.array(b)
Then use np.where to modify your array. The first argument is your condition, the second is the value you want your array to have when the condition is satisfied and the the third is the value you want your array to have when the condition is not satisfied:
>>> np.where(b>-10**(-5), 0, b)
array([[ 0. , 0. , 0. , 0. , 0. ],
[ 0. , -0.1875, -0.125 , -0.0625, 0. ],
[ 0. , -0.125 , -0.25 , -0.125 , 0. ],
[ 0. , -0.0625, -0.125 , -0.1875, 0. ],
[ 0. , 0. , 0. , 0. , 0. ]])

How to add rows to a matrix with pad?

I have a matrix like this:
profile=np.array([[0,0,0.5,0.1],
[0.3,0,0,0],
[0,0,0.1,0.9],
[0,0,0,0.1],
[0,0.5,0,0]])
And I want to add a row before and after filled with zeros. How can I do that?
I thought of using np.pad but not sure how.
Output should be:
np.array([[0,0,0,0],
[0,0,0.5,0.1],
[0.3,0,0,0],
[0,0,0.1,0.9],
[0,0,0,0.1],
[0,0.5,0,0]
[0,0,0,0]])
The np.pad function allows you to specify the axes you want to pad:
In [3]: np.pad(profile, ((1, 1), (0, 0)))
Out[3]:
array([[0. , 0. , 0. , 0. ],
[0. , 0. , 0.5, 0.1],
[0.3, 0. , 0. , 0. ],
[0. , 0. , 0.1, 0.9],
[0. , 0. , 0. , 0.1],
[0. , 0.5, 0. , 0. ],
[0. , 0. , 0. , 0. ]])
The nested tuple can be read as: pad 1 array "above", and 1 array "below" axis 0, and pad 0 arrays "above" and 0 arrays "below" axis 1.
Another example, which pads five columns "after" on axis 1:
In [4]: np.pad(profile, ((0, 0), (0, 5)))
Out[4]:
array([[0. , 0. , 0.5, 0.1, 0. , 0. , 0. , 0. , 0. ],
[0.3, 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ],
[0. , 0. , 0.1, 0.9, 0. , 0. , 0. , 0. , 0. ],
[0. , 0. , 0. , 0.1, 0. , 0. , 0. , 0. , 0. ],
[0. , 0.5, 0. , 0. , 0. , 0. , 0. , 0. , 0. ]])
You can use np.pad:
out = np.pad(profile, 1)[:, 1:-1]
Output:
>>> out
array([[0. , 0. , 0. , 0. ],
[0. , 0. , 0.5, 0.1],
[0.3, 0. , 0. , 0. ],
[0. , 0. , 0.1, 0.9],
[0. , 0. , 0. , 0.1],
[0. , 0.5, 0. , 0. ],
[0. , 0. , 0. , 0. ]])
Because np.pad pads it on all sides (left and right, in addition to top and bottom), [:, 1:-1] slices off the first and last columns.

bool masking in numpy array matrices

I have following program
import numpy as np
arr = np.random.randn(3,4)
print(arr)
regArr = (arr > 0.8)
print (regArr)
print (arr[ regArr].reshape(arr.shape))
output:
[[ 0.37182134 1.4807685 0.11094223 0.34548185]
[ 0.14857641 -0.9159358 -0.37933393 -0.73946522]
[ 1.01842304 -0.06714827 -1.22557205 0.45600827]]
I am looking for output in arr where values greater than 0.8 should exist and other values to be zero.
I tried bool masking as shown above. But I am able to slove this. Kindly help
I'm not entirely sure what exactly you want to achieve, but this is what I did to filter.
arr = np.random.randn(3,4)
array([[-0.04790508, -0.71700005, 0.23204224, -0.36354634],
[ 0.48578236, 0.57983561, 0.79647091, -1.04972601],
[ 1.15067885, 0.98622772, -0.7004639 , -1.28243462]])
arr[arr < 0.8] = 0
array([[0. , 0. , 0. , 0. ],
[0. , 0. , 0. , 0. ],
[1.15067885, 0.98622772, 0. , 0. ]])
Thanks to user3053452, I have added one more solution which the original data will not be changed.
arr = np.random.randn(3,4)
array([[ 0.4297907 , 0.38100702, 0.30358291, -0.71137138],
[ 1.15180635, -1.21251676, 0.04333404, 1.81045931],
[ 0.17521058, -1.55604971, 1.1607159 , 0.23133528]])
new_arr = np.where(arr < 0.8, 0, arr)
array([[0. , 0. , 0. , 0. ],
[1.15180635, 0. , 0. , 1.81045931],
[0. , 0. , 1.1607159 , 0. ]])

Changing the structure of np.array in Python

I have the following array structure.
array([[ 0.3, 0.1, 0. , 1. , 0. , 0. , 2.7],
[ 0.5, 0.5, 0. , 0. , 1. , 0. , 6. ],
[ 0.6, 0.4, -1. , 0. , 0. , 1. , 6. ]])
How can I change to the following structure?
array([[ 0.3, 0.1, 0. , 1. , 2.7],
[ 0.5, 0.5, 0. , 0. , 6. ],
[ 0.6, 0.4, -1. , 0. , 6. ]])
Assuming array is stored in a variable arr use indexing:
arr[:,[0, 1, 2, 3, 6]]

numpy merge upper and lower triangular

I essentially would like to do the opposite of this question. I have two matrixes that have been split with np.tril or np.triu and I want to recombine them into a single matrix.
A = array([[ 0. , 0. , 0. ],
[ 0.1, 0. , 0. ],
[ 0.6, 0.5, 0. ]])
B = array([[ 0. , 0.4, 0.8],
[ 0. , 0. , 0.3],
[ 0. , 0. , 0. ]])
And what I want it to look like is
array([[ 0. , 0.4, 0.8],
[ 0.1, 0. , 0.3],
[ 0.6, 0.5, 0. ]])
Is there an inbuilt numpy function to do this?
You mean A+B ?
import numpy
A = numpy.array([[ 0. , 0. , 0. ],
[ 0.1, 0. , 0. ],
[ 0.6, 0.5, 0. ]])
B = numpy.array([[ 0. , 0.4, 0.8],
[ 0. , 0. , 0.3],
[ 0. , 0. , 0. ]])
print A+B
returns
array([[ 0. , 0.4, 0.8],
[ 0.1, 0. , 0.3],
[ 0.6, 0.5, 0. ]])
If the values are strings, then this works as long as B is the upper triangle.
A = np.array([[ 0. , 0. , 0. ],
[ '0.1**', 0. , 0. ],
[ 0.6, '0.5**', 0. ]])
B = np.array([[ 0. , 0.4, '0.8***'],
[ 0. , 0. , 0.3],
[ 0. , 0. , 0. ]])
for i in range(0,len(A)):
for j in range(0,i):
B[i,j]=A[i,j]
B
Returns
array([['0.0', '0.4', '0.8***'],
['0.1**', '0.0', '0.3'],
['0.6', '0.5**', '0.0']], dtype='<U32')

Categories