Find and replace specific value in numpy ndarray? - python

I want to iterate through a numpy ndarray and, if any values are less than X, replace one of them with X.
I have tried doing array_name[ array_name < X] = X but this replaces all of the values that are less than X.
I can use a for loop, but I feel like there's probably a more concise way already bundled with numpy.
for i in array_name:
if i < X:
i = X
break
Is there a way to do this more elegantly?

array_name < X
Returns same array but with True or False. Then you can just pick an index where the cell is True
idx = np.argwhere(array_name < X)[i]
array_name[idx] = value
Here, you can choose i arbitrarily

Related

How to iterate over a numpy matrix based on a condition of another nump array?

I have a matrix X, and the labels to each vector of that matrix as a np array Y. If the value of Y is +1 I want to multiply the vector of matrix X by another vector W. If the value of Y is -1 I want to multiply the vector of matrix X by another vector Z.
I tried the following loop:
for i in X:
if Y[i] == 1:
np.sum(np.multiply(i, np.log(w)) + np.multiply((1-i), np.log(1-w)))
elif Y[i] == -1:
np.sum(np.multiply(i, np.log(z)) + np.multiply((1-i), np.log(1-z)))
IndexError: arrays used as indices must be of integer (or boolean) type
i is the index of X, but I'm not sure how to align the index of X to the value in that index of Y.
How can I do this?
Look into np.where, it is exactly what you need:
res = np.where(Y == +1, np.dot(X, W), np.dot(X, Z))
This assumes that Y can take only value +1 and -1. If that's not the case you can adapt the script above but we need to know what do you expect as result when Y takes a different value.
Also, try to avoid explicit for loops when using numpy, the resulting code will be thousands of times faster.
While it is better to use a no-iteration approach, I think you need a refresher on basic Python iteration.
Make an array:
In [57]: x = np.array(['one','two','three'])
Your style of iteration:
In [58]: for i in x: print(i)
one
two
three
to iterate on indices use range (or arange):
In [59]: for i in range(x.shape[0]): print(i,x[i])
0 one
1 two
2 three
enumerate is a handy way of getting both indices and values:
In [60]: for i,v in enumerate(x): print(i,v)
0 one
1 two
2 three
Your previous question had the same problem (and correction):
How to iterate over a numpy matrix?

Select values from array subject to a condition

I have a series X, containing N values. I would like to select values of X subject to the condition X[i] > V. I would think that something like:
Y = X[(X[:] > V)]
Would work. For now, I am getting a null set, even though I know that a subset of the values in X fulfill this condition.
Am I writing this incorrectly?
The code you give is correct if you want to compare each X[i] with each V[i]. Notice
>>> import numpy as np
>>> x = np.array(range(5))
>>> v = np.array([3]*5)
>>> x[x > v]
array([4])
If the original is what you did want re-inspect your x and v. Notice you need not add an empty comprehension [:] to x, although it will not change the output. What it seems you want (from claiming this is not working) are all the x greater than any element of V? If so take the min of v and perform the same mask
x[x > np.min(v)]

Splitting array of coordinates dependent on the Y value in Python

I have an array of coordinates, and I would like to split the array into two arrays dependent on the Y value when there is a large gap in the Y value. This post: Split an array dependent on the array values in Python does it dependent on the x value, and the method I use is like this:
array = [[1,5],[3,5],[6,7],[8,7],[25,25],[26,50],.....]
n = len(array)
for i in range(n-1):
if abs(array[i][0] - array[i+1][0]) >= 10:
arr1 = array[:i+1]
arr2 = array[i+1:]
I figured that when I want to split it dependent on the Y value I could just change:
if abs(array[i][0] - array[i+1][0]) to if abs(array[0][i] - array[0][i+1])
This does not work and I get IndexError: list index out of range.
I'm quite new to coding and I'm wondering why this does not work for finding gap in Y value when it works for finding the gap in the X value?
Also, how should I go about splitting the array depending on the Y value?
Any help is much appreciated!
you have to switch to this:
array = [[1,5],[3,5],[6,7],[8,7],[25,25],[26,50]]
n = len(array)
for i in range(n-1):
if abs(array[i][1] - array[i+1][1]) >= 10:
arr1 = array[:i+1]
arr2 = array[i+1:]

Python - If array is in range of other array

Meaning "if each item is within range of other item with the same index".
price = [1, 2]
budget = [5, 7]
This works:
if price[0] in range(budget[0]) and price[1] in range(budget[1]):
affordable = True
I figure there's some way to just reference the whole array though. Like so: if price in budget:
You could use:
if all(x in range(y) for x,y in zip(price,budget)):
affordable = True
This will create tuples of price[i],budget[i] and then for each of these tuples we check that price[i] is in range(budget[i]). Nevertheless, you can optimize this further to:
if all(0 <= x < y for x,y in zip(price,budget)):
affordable = True
Note that this makes the assumption that prices are all integers. If you however use x in range(y) it will fail if x is not an integer. So 0.7 in range(10) would fail whereas our second approach will succeed (but it depends of course on what you want).
Assuming that both prices and budgets must be non-negative, using in range seems to be over-complicating things. Instead, you could just use the < operator.
Regardless of whether you use < or in range, it seems like the easiest approach would be to zip both lists and apply the condition on the pairs:
if (all([x[0] >= x[1] for x in zip(budget, price)])):
affordable = True

How to use map lambda of python to make a element to a certain number?

I have a numpy.array called p2De. The first row has multiple elements may larger than 1. I want to set the elements which smaller than 1 to 1. Following is my code, but shows error... why? How to fix it?
bounde=1
p2De[:0]=map(lambda x:bounde if (x < bounde),p2Di[:0])
File "C:\Users\wange\workspace\cathode\src\diffusion.py", line 86
p2De[:0]=map(lambda x:bounde if (x < bounde),p2Di[:0])
^
SyntaxError: invalid syntax
You need to specify an else for your lambda function :
lambda x:bounde if (x < bounde) else #stuff
It should be
lambda x:bounde if (x < bounde) else x
You can also use list comprehension, which is more readable. Also, I would use the max builtin function instead of your lambda:
p2De[:0] = [max(x, bounde) for x in p2Di[:0]]
As others have noted, the syntax problem is in the lambda.
I don't think you want p2De[:0] - that's an empty array. p2De[0] is the 1st row. p2De[0,:] is the same, and makes it clear to the human readers that you have selected the 1st row of a 2d array.
The use of a map or comprehension works, but they don't offer much of an advantage, if any, over a simple loop (since you don't need to replace all of the values):
for i,v in enumerate(p2De[0,:]):
if v<1:
p2De[0,i] = 1
But none of these iterations is good numpy practice. You should try to think in terms of vector operations. A common practice is to use a boolean mask (or indexing) to select the values that should be changed:
I = p2De[0,:]<1 # boolean vector
p2De[0, I] = 1
p2De[0,p2De[0,:]<1]=1 # or one line form
There is also a numpy function that applies limits like this, np.maximum:
p2De[0,:] = np.maximum(p2De[0,:], 1)
np.clip applies both minimum and maximum bounds:
p2De[0,:] = np.clip(p2De[0,:], minbd, maxbd)
np.clip(p2De[0,:], minbd, maxbd, p2De[0,:]) # alt calling method
The Python(3) bosses encourage us to use functions and comprehensions over maps and lambdas. For example if plist was a list like your p2De[0,:] row:
def clip(x):
return 1 if x<1 else x
plist = [clip(x) for x in plist]
plist = [min(x, 1) for x in plist] # using a builtin for this simple case
say if you have a list a, you can do something like this:
a=[2,3,1,7,0,0,8]
bounde=1
b = map(lambda n: n if n > bounde else bounde,a)
print b

Categories

Resources