Home > Mobile >  Is it possible to use a forloop to store arrays as unique variables?
Is it possible to use a forloop to store arrays as unique variables?

Time:11-13

Does anyone know if it's possible to use a forloop to create arrays and store them as unique variables?

For example. I have a function that takes a three-dimensional array and masks elements within the array based on given parameters:

def masc(arr,M,N,O,P,z):
        return(np.ma.masked_where((arr[:,:,2] <= z 0.05)*(arr[:,:,2] >= z-0.05)*(arr[:,:,0]>=M)*((arr[:,:,0])<=O)*(arr[:,:,1]<=N)*((arr[:,:,1])>=P-10), arr[:,:,2]))

where arr is a three dimensional array.

my array is defined by variable 'xyz' and is a grid x columns and y rows with corresponding z values. Something like this:

xyz = 
[[40,50,2],
[41,50,5]
.....
[57,65,15]]

(these are totally made up numbers)

I run this function iteratively to create unique masked arrays based on a xyz and given variables. The output is the array xyz with certain elements masked based on the subsetting given in the masc function.

masked_array1 = masc(xyz,x1,y1,X1,Y1,z1)
masked_array2 = masc(xyz,x2,y2,X2,Y2,z2)
.
.
.
masked_arrayn = masc(xyz,xn,yn,Xn,Yn,zn)

I'd like to put this in a forloop where I can generate all of those unique arrays based on a given input arrays. Say it would work through an array of each variable:

X = [1,2,3]
Y = [1,2,3]
x = [4,5,6]
y = [4,5,6]
z = [7,8,9]

and the for loop would calculate the corresponding masked array for each one of those values. So if I were to just do it manually myself it would look like:

masked_array1 = masc(xyz,x[1],y[1],X[1],Y[1],z[1])
masked_array2 = masc(xyz,x[2],y[2],X[2],Y[2],z[2])
masked_array3 = masc(xyz,x[3],y[3],X[3],Y[3],z[3])

Does anyone know if it's possible to use a forloop to create unique variables such that I'd achieve multiple output arrays? Would I have to create one large array that encompasses all the masked arrays?

EDIT: I went in and added some detail and example input output. Hopefully that helps clarify my question.

CodePudding user response:

For your function and some data

import numpy as np

def masc(arr,M,N,O,P,z):
    return(np.ma.masked_where((arr[:,:,2] <= z 0.05)*(arr[:,:,2] >= z-0.05)*(arr[:,:,0]>=M)*((arr[:,:,0])<=O)*(arr[:,:,1]<=N)*((arr[:,:,1])>=P-10), arr[:,:,2]))

arr = np.random.rand(10, 10, 3)

X = [1,2,3]
Y = [1,2,3]
x = [4,5,6]
y = [4,5,6]
z = [7,8,9]

you can iterate over all your parameters like

for xx, yy, XX, YY, zz in zip(x, y, X, Y, z):
    masc(arr, xx, yy, XX, YY, zz)

or create a single output array like

out1 = np.array([
    masc(arr, xx, yy, XX, YY, zz)
    for xx, yy, XX, YY, zz in zip(x, y, X, Y, z)
])

alternatively you can use broadcasting

def masc2(arr,M,N,O,P,z):
    M = np.asarray(M)[..., None, None]
    N = np.asarray(N)[..., None, None]
    O = np.asarray(O)[..., None, None]
    P = np.asarray(P)[..., None, None]
    z = np.asarray(z)[..., None, None]

    condition = (
        (arr[:,:,2] <= z   0.05) *
        (arr[:,:,2] >= z - 0.05) *
        (arr[:,:,0] >= M) *
        (arr[:,:,0] <= O) *
        (arr[:,:,1] <= N) *
        (arr[:,:,1] >= P - 10)
    )
    data = arr[:,:,2]
    return np.ma.masked_where(condition, np.broadcast_to(data, condition.shape))

and do the entire operation in one single call

out2 = masc2(arr, x, y, X, Y, z)

and the outputs are identical

np.allclose(out1, out2)
# True
  • Related