-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
zamir
  • 2,144
  • 1
  • 11
  • 23
Chiheb
  • 31
  • 4

1 Answers1

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)]
Aymen
  • 34
  • 4
  • Please provide a description of the code when answering the question. Also note that the OP said 'NO' for loops – BenT Jul 02 '19 at 02:56
  • I rework the rule number 3 and succeeded to make it without loop – Aymen Jul 02 '19 at 15:32
  • I need to take some time to explain the global approach which is based on the following post https://stackoverflow.com/questions/30068020/numpy-calculate-based-on-previous-element – Aymen Jul 02 '19 at 15:38