Finding specific values and replacing them by others. Python - python

I am very new to programming. I have code in matlab:
x2(x2>=0)=1;
x2(x2<0)=-1;
%Find values in x2 which are less than 0 and replace them with -1,
%where x2 is an array like
0,000266987932788242
0,000106735120804439
-0,000133516844874253
-0,000534018243439120
I tried to do this in Python using code
if x2>=0:
x2=1
if x2<0:
x2=-1
This returns ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
How should I do it so that I get all the positive replaced by 1 and negatives by -1 and STORE all of this in the x2 for example, not just print, so that I could use it later to do some other stuff.

You can use numpy's ability to index over boolean array.
import numpy as np
x = np.array([-5.3, -0.4, 0.6, 5.4, 0.0])
not_neg = x >= 0 # creates a boolean array
x[not_neg] = 1 # index over boolean array
x[~not_neg] = -1
Result:
>>> x
array([-1., -1., 1., 1., 1.])

First:
x2 = [0.000266987932788242, 0.000106735120804439, -0.000133516844874253, -0.000534018243439120]
print [1 if num >= 0 else num for num in x2]
Output
[1, 1, -0.000133516844874253, -0.000534018243439120]
Second:
x2 = [-1, 2, -3, 4]
print [-1 if num < 0 else num for num in x2]
Output
[0.000266987932788242, 0.000106735120804439, -1, -1]
If you need both of them in a single statement
x2 = [0.000266987932788242, 0.000106735120804439, -0.000133516844874253, -0.000534018243439120]
x2 = [-1 if num < 0 else 1 for num in x2]
print x2
Output
[1, 1, -1, -1]

Related

Fancy indexing to matrix operations

Suppose:
A=np.array([1,2,0,-4])
B=np.array([1,1,1,1])
C=np.array([1,2,3,4])
With fancy indexing I can assign a scalar value to C wherever A > 0.
C[A > 0]= 1
But is there anyway to get something like C = B/A wherever A > 0 while preserving the original values of C for A <= 0 with fancy indexing ? If I try something like
C[A > 0] = B/A
I get an error like:
<input>:1: RuntimeWarning: divide by zero encountered in true_divide
Traceback (most recent call last):
File "<input>", line 1, in <module>
ValueError: NumPy boolean array indexing assignment cannot assign 4 input values to the 2 output values where the mask is true
I can get the result with a for loop or making copies of A & C where :
D = np.copy(A)
E = np.copy(C)
D[ D <= 0]= 1
E=B/A
E[A <=0] = C
or set C=Run(A,B) where
def Run(A,B):
C=np.zeros(A.shape[0],A.shape[1])
for i in range(len(A)):
if A[i] != O:
C[i] = A[i]/B[i]
else:
C[i] = C[i]
But i was just wondering if there was a more direct way to do it without adding so many steps if i am looping millions of times. Thanks.
You can index the operands: C[A > 0] = B[A > 0] / A[A > 0]. You might want to compute A > 0 once, and reuse it, e.g.
mask = A > 0
C[mask] = B[mask] / A[mask]
A more efficient alternative is to use the where parameter of np.divide or np.floor_divide. For example,
In [19]: A = np.array([1, 2, 0, -4])
In [20]: B = np.array([1, 1, 1, 1])
In [21]: C = np.array([1, 2, 3, 4])
In [22]: np.floor_divide(B, A, where=A > 0, out=C)
Out[22]: array([1, 0, 3, 4])
In [23]: C
Out[23]: array([1, 0, 3, 4])
I had to use floor_divide because all the arrays are integer arrays, and numpy.divide creates a floating point array, so that function will complain about the type mismatch if the out array is an integer array. If you want a floating point result, C should be an array of floating point values:
In [24]: C = np.array([1., 2., 3., 4.])
In [25]: np.divide(B, A, where=A > 0, out=C)
Out[25]: array([1. , 0.5, 3. , 4. ])
In [26]: C
Out[26]: array([1. , 0.5, 3. , 4. ])

efficient way to manipulating numpy array

So let's say I have a numpy array a= np.array([1,2,3,4,5]) and a value x=4, then I want to create a numpy array of values -1 and 1 where there is a 1 in the 4th position and -1 everywhere else.
Here is what I tried:
for i in range(a):
if i == x:
a[i]=1
else:
a[i]=-1
Is this good?
No, this is not numpy'ish
b=-np.ones(a.shape)
b[x] = 1
Edit: added example
import numpy as np
x=3
a= np.array([1, 2, 3, 4, 5])
b=-np.ones(a.shape)
b[x] = 1
print(b)
> [-1. -1. -1. 1. -1.]
Try:
import numpy as np
a= np.array([1,2,3,4,5])
x=np.where(a==4, 1, -1)
print(x)
Output:
[-1 -1 -1 1 -1]
[Program finished]
try this:
b = np.array([1 if i == 4 else -1 for i in range(a.shape)])
Another alternative. Utilizes casting from bool to int.
b=2*(a==x)-1

Finding consecutive and identical integer into a vector

I have vectors with 0 and 1.
a = np.array([1,1,0,0])
b = np.array([1,0,0,1])
c = np.array([0 1 1 0])
d = np.array([0 1 0 1])
I would like to implement a function checking if the 1 are consecutive in the vector by disregarding the end of the vector, i.e. last element wih first element. Expected results will be:
check(a) --> True
check(b) --> True
check(c) --> True
check(d) --> False
The easy solution will be to scroll through each vector. However I feel that an easier and smarter is doable with some np.diff or np.nonzero combination. Any idea?
Thanks a lot.
You could use np.roll + np.logical_and + np.count_nonzero
import numpy as np
def check(arr):
return np.count_nonzero(np.logical_and(np.roll(arr, 1), arr)) > 0
a = np.array([1, 1, 0, 0])
b = np.array([1, 0, 0, 1])
c = np.array([0, 1, 1, 0])
d = np.array([0, 1, 0, 1])
print(check(a))
print(check(b))
print(check(c))
print(check(d))
Output
True
True
True
False
Maybe you can try something like this,
def check(k):
return any( i in np.diff(np.where(k==1)) for i in [1, len(k)-1])
np.where(k==1), this will return a list of indices where your vector is 1.
np.diff(np.where(k==1)), this will evalute the difference between consequative indices where your vector is 1.
Finally any( i in np.diff(np.where(k==1)) for i in [1, len(k)-1]) this will check if there are consecutive 1's. Either if their difference is 1 or length of your vector - 1.

Is there any operation on two numpy array to discard zero values?

Suppose we have two numpy array x1 and x2 like below:
x1 = np.array([[0,2,9,1,0]])
x2 = np.array([[7,3,0,6,8]])
Is there any operation like:
x2(operation)x1 = array([[ 0, 3, 0, 6, 0]])
i.e. if x1 or x2 is 0 at any index then make the result array's index value as zero. Otherwise, keep x2 as it is.
Use numpy.where:
x3 = np.where(x1 == 0, x1, x2)
print(x3)
Output:
[[0 3 0 6 0]]
Given that you want to keep x2 but make it zero in the case x1 is zero, just multiply x2 by the boolean of x1.
>>> x2 * x1.astype(bool)
array([[0, 3, 0, 6, 0]])
Note that if x2 is zero, the result is zero as expected.

Value Error on computing matrix elements sum

I am trying to write a function that adds all elements in a matrix. The special condition is if an element in the matrix is 0, we count the element below this 0 also 0. For example:
matrix =
[[0, 1, 1, 2],
[0, 5, 0, 0],
[2, 0, 3, 3]]
Should return 9 because 1+1+2+5=9
Here is what I have for my code, I got this error, ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all(). Can someone please help?
import numpy as np
def matrixElementsSum(matrix):
a=np.array([matrix])
sumofcolumn=0
sum=0
for x in range(len(a)): # x in matrix row
for y in range(len(a[0])): #y in matrix col
if a[x][y]==0:
a[x+1][y]==0 #set next row same column=0
sumofcolumn+=a[x][y] #sumofcolumn is a column sum
for x in sumofcolumn:
sum+=x
return sum
You could rotate, flatten, and them use a simple comprehension:
import numpy as np
matrix = [[0, 1, 1, 2], [0, 5, 0, 0], [2, 0, 3, 3]]
matrix = np.rot90(matrix).flatten()
indices = set(np.where(matrix==0)[0]+1) # set of indices to the right of 0 fast lookup
final = sum(e for i,e in enumerate(matrix) if i not in indices)
print(final)
Output:
9
When you rotate and flatten, you are left with:
[2 0 3 1 0 3 1 5 0 0 0 2]
And if you notice, all the values that had 0 above them in your matrix, now have 0 to the left of them, and you can use the list comprehension to ignore these, and then find the sum of the result.
I'm sure there is a way to do this without the rotation, but I feel this way is much easier to visualize.
Find the woking code with inline comments where you got wrong.
import numpy as np
def matrixElementsSum(matrix):
a = np.array(matrix) # no need of appending in []
my_sum = 0 # sumofcolumn not required
for x in range(len(a)): # x in matrix row
for y in range(len(a[x])): # y in matrix col
if a[x][y] == 0 and x < len(a)-1: # handling last index
a[x+1][y] = 0 # set next row same column=0
my_sum += a[x][y] # adding value to sum..
# no for loop required, you are not appending values to a list.
# it's an integer and it's declared outside of loops.
return my_sum
matrix = [[0, 1, 1, 2], [0, 5, 0, 0], [2, 0, 3, 3]]
print(matrix)
print(matrixElementsSum(matrix))
You can do this as follows
total = 0
zeros = []
for row in matrix:
total += sum([val for ix, val in enumerate(row) if not ix in zeros])
zeros = [ix for ix, i in enumerate(row) if i == 0]
total
It can be done with rows-to-columns and flat list where index is increased by 2 if value is 0:
def matrix_elements_sum(matrix):
lst = sum(list(zip(*matrix)), ()) # rows-to-columns and to flat list
total = 0
i = 0
while i < len(lst):
if lst[i] != 0:
total += lst[i]
i += 1
else:
i += 2
return total
def matrixElementsSum(matrix):
totalSum = 0
for row in range(len(matrix)):
for col in range (len(matrix[0])):
if matrix[row][col] == 0 and row != len(matrix) -1:
matrix[row+1][col] = 0
else:
totalSum = totalSum + matrix[row][col]
return totalSum
I know this is vary late...
def matrixElementsSum(matrix):
sum = 0
for r in range(len(matrix)):
for c in range(len(matrix[r])):
if (matrix[r][c] != 0):
if (r==0):
sum += matrix[r][c]
else:
if(matrix[r-1][c] !=0):
sum += matrix[r][c]
else:
if(r == len(matrix)-1):
continue
else:
matrix[r+1][c] = 0
return sum

Categories

Resources