Skip to content
Advertisement

Python : Use of the previous value generated from a function in the same function

I am trying to have a rolling average of all the highs of [‘RSIndex’] greater than 52, series will have NaN value if the first ref value is less than 52, but I want to have the previous iterated value of [‘high_r’] that the function has generated if any other ref value is less than 52. If, anyone has any solution to this, i ll be really grateful. Thanks

def AvgHigh(src, val) :
    for a in range(len(src)) :
        if src[a] > val :
            yield src[a]
        elif src[a] <= val and a == 0 :
            yield np.nan
        elif src[a] <= val and a != 0 :
            yield src[a-1]

df1['high_r'] = pd.Series(AvgHigh(df1['RSIndex'], 52))
df1['RSI_high'] = df1['high_r'].rolling(window = 25, min_periods = 25).mean()

Desired Output:

Desired Output

Advertisement

Answer

You can use np.where() and .shift() to simply your codes, as follows:

df1['high_r'] = np.where(df1['RSIndex'] > 52, df1['RSIndex'], df1['RSIndex'].shift())
df1['RSI_high'] = df1['high_r'].rolling(window = 25, min_periods = 25).mean()

np.where() checks for the condition of first parameter, if the condition is true, it uses values from the second parameter [similar to your if statement in the loop]. When the condition is false [similar to your 2 elif statements in the loop]., it uses the values from the third parameter.

.shift() takes the previous row value [similar to your second elif statement] and for the first value where there is no previous, it takes the value given by its fill_value parameter, which defaults to use np.nan for column of numeric values. As such, it achieves the same effect of your first elif to set np.nan for first entry.

Edit

If you want the values to take from last loop iteration instead of initial column values, you can define a list to accumulate the values of the loop, as follows:

def AvgHigh(src, val) :
    dat_list = []
    last_src = np.nan              # init variable that keeps the prev iteration value
    for a in range(len(src)) :
        if src[a] > val :
#            yield src[a]
            dat_list.append(src[a])
            last_src = src[a]          # update prev iteration value (for subsequent iteration(s))
        elif (src[a] <= val) and (a == 0) :
#            yield np.nan
            dat_list.append(np.nan)
        elif (src[a] <= val) and (a != 0) :
#            yield src[a-1]
            dat_list.append(last_src)
        
    return dat_list

df1['high_r'] = AvgHigh(df1['RSIndex'], 52)
df1['RSI_high'] = df1['high_r'].rolling(window = 25, min_periods = 25).mean()
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement