Numpy - IF element is less than or equal to, then pass - python

I am trying to sort through a list of values in NUMPY / UPROOT, and I am having trouble with the formatting, as I am new to UPROOT.
The values are in some other list, and we'll call the values in one by one with a name, x.
If the values of x is greater than or equal to 5, I want to add it to the array, which is initially empty. If the number is less than 5, then we move onto the next number.
specifically, I need help with how to format the "greater than equal to"
array = []
if x is greater than or equal to 5:
array.append(x)
else:
return 0
Thanks everyone!

Using numpy you can do something like:
import numpy as np
# Initialize array
array = np.array([])
# Make some random values for x
x = np.floor(np.random.rand(10)*10)
for i in x: # Loop through x
if i >= 5: # If value is bigger or equal to 5
array = np.append(array, i) # add to array
So, "greater than equal to" is just >=

you're using a python list, which is different from numpy arrays. either way the following code should work
X = np.random.random(size= [10]) # array containing x values
if you want an numpy array
arr = X[X >= 5]
if you want a list
arr = list(X[X >= 5])

Related

Iterating a function over an array

Posing the title of this question differently.
I have a function that take a three dimensional array and masks certain elements within the array based on specific conditions. See below:
#function for array masking
def masc(arr,z):
return(np.ma.masked_where((arr[:,:,2] <= z+0.05)*(arr[:,:,2] >= z-0.05), arr[:,:,2]))
arr is a 3D array and z is a single value.
I now want to iterate this for multiple Z values. Here is an example with 2 z values:
masked_array1_1 = masc(xyz,z1)
masked_array1_2 = masc(xyz,z2)
masked_1 = masked_array1_1.mask + masked_array1_2.mask
masked_array1 = np.ma.array(xyz[:,:,2],mask=masked_1)
The masked_array1 gives me exactly what i'm looking for.
I've started to write a forloop to iterate this over a 1D array of Z values:
mask_1 = xyz[:,:,2]
for i in range(Z_all_dim):
mask_1 += (masc(xyz,Z_all[i]).mask)
masked_array1 = np.ma.array(xyz[:,:,2], mask = mask_1)
Z_all is an array of 7 unique z values. This code does not work (the entire array ends up masked) but i feel like i'm very close. Does anyone see if i'm doing something wrong?
Your issue is that before the loop you start with mask_1 = xyz[:,:,2]. Adding a boolean array to a float will cast the boolean to 1s and 0s and unless your float array has any 0s in it, the final array will be all nonzero values, which then causes every value to get masked. Instead do
mask_1 = masc(xyz, Z_all[0]).mask
for z in Z_all[1:]:
mask_1 += masc(xyz, z).mask
Or avoiding any loops and broadcasting your operations
# No need to pass it through `np.ma.masked_where` if
# you're just going to extract just the boolean mask
mask = (xyz[...,2,None] <= Z_all + 0.05) * (xyz[...,2,None] >= Z_all - 0.05)
mask = np.any(mask, axis=-1)

Calculation between values in numpy array

New to python and need some help. I have a numpy array tuple with a shape of (1, 8760) with numbers within each of the 8760 locations. I've been trying to calculate if the values is between -2 and 2 then my new variable will be 0 else just keep the same value in the new variable. Here is what I tried and many others but I probably don't understand the array concept fully.
for x in flow:
if 2 > x < -2:
lflow = 0
else:
lflow = flow
I get this error:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
From what I read those functions gives me a true or false but I want to calculate of value instead of telling me if it matches or not. Please help.
Thanks
If your shape is (1,8760) an array of 8760 elements is assigned to x in your iteration, because the loop iterates the first axis containing one element of size 8760.
Furthermore I'd suggest to use "where" function instead of a loop:
# create a random array with 100 values in the range [-5,5]
a = numpy.random.random(100)*10 - 5
# return an array with all elements within that range set to 0
print numpy.where((a < -2) | (a > 2), a, 0)
Numpy uses boolean masks to select or assign values to arrays in bulk. For example, given the array
A = np.array([-3,-1,-2,0,1,5,2])
This mask represents all the values in A that are less than -2 or greater than 2
mask = (A < -2) | (A > 2)
Then use it to assign those values to 0
A[mask] = 0
This is much faster than using a regular loop in python, since numpy will perform this operation in c or fortran code

Getting index of maximum value in nested list

I have a nested list a made of N sublists each of them filled with M floats. I have a way to obtain the index of the largest float using numpy, as shown in the MWE below:
import numpy as np
def random_data(bot, top, N):
# Generate some random data.
return np.random.uniform(bot, top, N)
# Generate nested list a.
N, M = 10, 7 # number of sublists and length of each sublist
a = np.asarray([random_data(0., 1., M) for _ in range(N)])
# x,y indexes of max float in a.
print np.unravel_index(a.argmax(), a.shape)
Note that I'm using the sublist index and the float index as x,y coordinates where x is the index of a sublist and y the index of the float inside said sublist.
What I need now is a way to find the coordinates/indexes of the largest float imposing certain boundaries. For example I would like to obtain the x,y values of the largest float for the range [3:5] in x and [2:6] in y.
This means I want to search for the largest float inside a but restricting that search to those sublists within [3:5] and in those sublists restrict it to the floats within [2:6].
I can use:
print np.unravel_index(a[3:5].argmax(), a[3:5].shape)
to restrict the range in x but the index returned is shifted since the list is sliced and furthermore I can think of no way to obtain the y index this way.
An alternative solution would be to set the values outside the range to be np.inf:
import numpy as np
# Generate nested list a.
N, M = 10, 7 # number of sublists and length of each sublist
a = np.random.rand(N, M)
# x,y indexes of max float in a.
print np.unravel_index(a.argmax(), a.shape)
A = np.full_like(a, -np.inf) # use np.inf if doing np.argmin
A[3:5, 2:6] = a[3:5, 2:6]
np.unravel_index(A.argmax(), A.shape)
You could turn 'a' into a matrix, which lets you easily index rows and columns. From there, the same basic command works to get the restricted indices. You can then add the start of the restricted indices to the result to get them in terms of the whole matrix.
local_inds = np.unravel_index(A[3:5,2:6].argmax(),A[3:5,2:6].shape)
correct_inds = np.asarray(local_inds) + np.asarray([3,2])
This won't work if you have more complicated index restrictions. If you have a list of the x and y indices you want to restrict by, you could do:
idx = [1,2,4,5,8]
idy = [0,3,6]
# make the subset of the data
b = np.asarray([[a[x][y] for y in idy] for x in idx])
# get the indices in the restricted data
indb = np.unravel_index(b.argmax(), b.shape)
# convert them back out
inda = (idx[indb[0]],idy[indb[1]])

Using arrays in an if statement condition

How do I use arrays in the condition part of an if statement? I want the program to check every element's absolute value, and return the appropriate part. This gave some hope: Function of Numpy Array with if-statement
But this technique isn't working in my case.
Here is the code I'm trying:
def v(x,y):
if x[abs(x)<a] and y[abs(y)<a]:
return #something 1
if x[a<abs(x)<b] and y[a<abs(y)<b]:
return #something 2
if x[b<abs(x)<R] and y[b<abs(y)<R]:
return #something 3
Here, x and y are arrays. (Actually a grid created by x,y = ogrid[-R:R:.01, -R:R:.01])
Edit: The best way I found (after much trial and error) is to use boolean arrays. Here's the code:
#Create a grid of coordinates. XY-Plane.
x,y=ogrid[-R:R+1:1,-R:R+1:1]
#Create the polar distance 2D array. Conditions are tested on this array.
r=sqrt(x**2+y**2)
#Create 2D array to hold the result
v=zeros([len(x*y),len(x*y)],float)
#idr is the boolean 2D array of same size and shape as r.
#It holds truth values wherever the condition is true.
idr=(r<a)
v[~invert(idr)]= #function 1 of r[~invert(idr)]
idr=((r>=a)&(r<b))
v[~invert(idr)]= #function 2 of r[~invert(idr)]
idr=(r>=b)&(r<=R)
v[~invert(idr)]= #function 3 of r[~invert(idr)]
print v
The values in v get updated at the correct locations.
Thanks for the help!
Try using all(), like in this:
import numpy
a = numpy.array([-1, -2, 1, 2, 3])
print(numpy.all(a > 0))
print(numpy.all(abs(a) > 0))
You get:
C:\Documents and Settings\XXX\Desktop>python test.py
False
True
So your first if statement would turn into this (assuming you have import numpy):
if numpy.all(abs(x) < a) and numpy.all(abs(y) < a):
return #something 1
If you wish to check the abslute value of every element, try this:
if( abs(x[1]) >= 3) #or whatever you want to check
if( abs(x[2]) >= 4) #or whatever
If x is an array that you are checking.
I hope this helps.

getting all rows where complex condition holds in scipy/numpy

what is the simplest way to get all rows where a complex condition holds for an ndarray that represents a 2d matrix? e.g. get all rows where all the values are above 5 or all the values are below 5?
thanks.
You probably know that boolean arrays can be used for indexing, e.g.:
import numpy as np
x = np.arange(10)
x2 = x[x<5]
For a boolean array, np.all lets you apply it across a given axis:
y = np.arange(12).reshape(3,4)
b = y < 6
b1 = np.all(b, axis=0)
b2 = np.all(b, axis=1)
y1 = y[b1]
y2 = y[b2]
It only returns the arrays which meet the criteria, so the shape is not preserved. (If you do need to preserve the shape, then take a look at masked arrays.)
This will give you the row indices of the rows where all values are lower or higher than 5:
x = numpy.arange(100).reshape(20,5)
numpy.where((x > 5).all(axis=1) ^ (x < 5).all(axis=1))
or more concisely (but not proceeding via the same logic):
numpy.where(((x > 5) ^ (x < 5)).all(axis=1))
To fetch the data, rather than the indices, use the boolean result directly:
x[((x > 5) ^ (x < 5)).all(axis=1)]

Categories