Skip to content Skip to sidebar Skip to footer

Getting The Maximum Upswing In Numpy Array

I am trying to write a function that calculates how much the biggest upside was in each array. The function below calculates between the max and the min but it does not get Expecte

Solution 1:

I think this should work, however I do suggest some better names for the variables (see below), I kept yours to show the difference.

def calc(arr):
    try:
        acc_max = np.minimum.accumulate(arr)
        result = (arr - acc_max).max()
        dip_idx = (arr - acc_max).argmax()
        max_idx= arr[:dip_idx].argmin()
        print("Result: {} Between Values: {},{} Indexes: {},{}".format(result, arr[max_idx],arr[dip_idx],max_idx,dip_idx))
        return result
    except:
        print("No Upside")

I changed arr + acc_max to arr - acc_max as well as arr[:dip_idx].argmin() to arr[:dip_idx].argmax()

Explanation: acc_max will be the lowest number found so far in the array. So, what you want to do is subtract this array form the original array, to get the diff between each element and the minimum number found so far in the array, i.e. arr - acc_max will contain all these diffs.

Then (arr - acc_max).max() will give you the maximum diff (which you are looking for), i.e. the maximum gain. So, result will hold the value for the maximum gain, while dip_idx will hold the index for the value where the maximum gain was achieved.

max_idx= arr[:dip_idx].argmin() will then find the minimum value for the array, before the max-gain-value was achieved, i.e. this will be the index for the "start" of the gain.

So, with some better naming for the variables:

def calc(arr):
    try:
        min_so_far = np.minimum.accumulate(arr)
        max_gain = (arr - min_so_far).max()
        max_gain_end_idx = (arr - min_so_far).argmax()
        max_gain_start_idx= arr[:max_gain_end_idx].argmin()
        print("Result: {} Between Values: {},{} Indexes: {},{}".format(          max_gain,arr[max_gain_end_idx],arr[max_gain_start_idx],max_gain_start_idx,max_gain_end_idx)
         )
        return max_gain
    except:
        print("No Upside")

Solution 2:

This is a classic example of what happens when you copy and paste a bunch of code without attempting to understand it. The first tip-off is

acc_max = np.minimum.accumulate(arr)

Why is the running minimum called acc_max? Another thing is that your code can not throw an error anywhere, which you would have noticed if you pasted a proper MCVE.

The correct answer is that you want to accumulate the running minimum, subtract it off the array, and find the maximum of the result. You don't have a result when the entire array is monotonically decreasing, which will lead to np.minimum.accumulate returning arr, and the difference being exactly zero everywhere.

def calc(arr):
    running_min = np.minimum.accumulate(arr)
    delta = arr - running_min
    if not delta.any():
        print('No upswing')
        return None
    max_idx = delta.argmax()
    result = delta[max_idx]
    min_idx = arr[:max_idx].argmin()
    print(f'Result: {result} Between values {arr[min_idx]}, {arr[max_idx]} at indices {min_idx}, {max_idx}')
    return result

This produces the expected results for all your test inputs.


Post a Comment for "Getting The Maximum Upswing In Numpy Array"