-1

I need to calculate array Z having array D (only using indexing, slicing and broadcasting, NO LOOPS):

D = [0, 0, 0, 0, 12, 36, 24, 24, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 36]

Z = [nan, nan, nan, nan, 12., 14.4, 15.36, 16.224, 16.224, 16.224, 16.224, 16.224, 16.224, 16.224, 16.224, 15.8016, 15.8016, 15.8016, 15.8016, 17.8214]

Rule#1: Before first non-zero value of D (here index < 4) => array Z values equal nan (here indices 0 to 3)

Rule#2: First non-zero value of D (here index 4, value 12) => array Z gets the value of A at that index (12)

Rule#3: Following Rule#2, if D is not equal to 0 at index i => Z[i] = Z[i-1] + 0.1 * (D[i] - Z[i-1])

ie:

ind=4: D[4]=12 => Z[4]=12 (Rule#2)

ind=5: D[5]=36 => Z[5]=12 + 0.1 * (36 - 12) = 14.4

ind=6: D[6]=24 => Z[6]=14.4 + 0.1 * (24 - 14.4) = 15.36

ind=7: D[7]=24 => Z[7]=15.36 + 0.1 * (24 - 15.36) = 16.224

Rule#4: If D is equal to 0 (here indice i = 8) => Z[i] = Z[i-1]

ie:

ind=8: D[8]=0 =>  D[8]=D[7]=16.224

1 Answer 1

1

I hope it can help:

def function_needed(D,alpha):
    #Rule 1
    Z=np.zeros(len(D))
    idx=(np.array(D)!=0).argmax(axis=0)
    Z[:idx] = np.NaN
    #Rule 2
    Z[idx]=D[idx]
    #Rule 3
    x=np.array(D)[np.nonzero(np.array(D))]
    n = len(x)
    y_1 = Z[idx]
    pot = (1-alpha)**np.arange(n-1, -1, -1)
    y = alpha*np.cumsum(pot * x)/pot+y_1*(1-alpha)**np.arange(1, n+1)
    Z[np.nonzero(D)]=y
    #Rule 4
    mask =(Z==0)
    idx = np.where(~mask,np.arange(mask.shape[0]),0)
    Z=Z[np.maximum.accumulate(idx,axis=0, out=idx)]
    return Z

testing=function_needed(D,0.1)

I developed the function called function_needed to make all rules once. This is the explanation step by step

Rule 1

1- Create an array with 0 of the same size of the original array D

Z=np.zeros(len(D))

2- Get the index of the first non zero value

idx=(np.array(D)!=0).argmax(axis=0)

3- Put NaN to all values prior to the first non zero value

Z[:idx] = np.NaN

Rule 2

1- fill Z with the first non zero demand at the index of the first non zero value of D

Z[idx]=D[idx]

Rule 3

There is new calculation of the Z only when there is non zero demand

1- Create X the array corresponding to D non zero

x=np.array(D)[np.nonzero(np.array(D))]

2- If we consider Y the calculation as proposed in the rule 3 for non zero demand. We remark that recursively each element of Y is given with the following formula

image of the formula

where y_1 is the first non zero value

n = len(x)

y_1 = Z[idx]

pot = (1-alpha)**np.arange(n-1, -1, -1)

y = alpha*np.cumsum(pot * x)/pot+y_1*(1-alpha)**np.arange(1, n+1)

Z[np.nonzero(D)]=y

At that stage Z is equal to

Z

Rule 4

Replace the 0 values obtained in the previous step by the first inferior non zero value. This is what we call foreward filling To do so:

mask =(Z==0)
idx = np.where(~mask,np.arange(mask.shape[0]),0)
Z=Z[np.maximum.accumulate(idx,axis=0, out=idx)]
Sign up to request clarification or add additional context in comments.

3 Comments

Please provide a description of the code when answering the question. Also note that the OP said 'NO' for loops
I rework the rule number 3 and succeeded to make it without loop
I need to take some time to explain the global approach which is based on the following post stackoverflow.com/questions/30068020/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.