Getting The Maximum Upswing In Numpy Array
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"