-
Notifications
You must be signed in to change notification settings - Fork 73
add new minmax function
#526
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 12 commits
57353a9
15ef75d
263b450
23010b3
deafd99
ead11ad
979916f
f146536
5712f77
785bcd8
aa3a41c
bb24ee3
e20b4d5
ef753a0
0647cf4
15daf3b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -91,6 +91,7 @@ Utilities | |
| .. autosummary:: | ||
| :toctree: generated/ | ||
|
|
||
| minmax | ||
| maxabs | ||
| variance_to_weights | ||
| grid_to_table | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -261,6 +261,137 @@ def maxabs(*args, nan=True, percentile=100): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nppercentile(combined_array, percentile) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def minmax(*args, nan=True, min_percentile=0, max_percentile=100): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Calculate the minimum and maximum values (or percentiles) of the given | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| array(s). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Use this to set the limits of your colorbars for non-diverging data. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Parameters | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ---------- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| args | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| One or more arrays. If more than one are given, a minimum and maximum | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| will be calculated across all arrays. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nan : bool, optional | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| If True, will use the ``nan`` version of numpy functions to ignore | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| NaNs. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| min_percentile: float | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Return the supplied percentile (0 to 100) instead of the minimum value | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| of the arrays. Defaults to 0, giving the minimum value. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| max_percentile : float | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Return the supplied percentile (0 to 100) instead of the maximum value | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| of the arrays. Defaults to 100, giving the maximum value. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Returns | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ------- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| min, max : float | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| The minimum and maximum (or percentile) values across all arrays. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Examples | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -------- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| >>> result = minmax((1, -10, 25, 2, 3)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| >>> tuple(map(float, result)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (-10.0, 25.0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| >>> result = minmax( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ... (1, -10.5, 25, 2), (0.1, 100, -500), (-200, -300, -0.1, -499) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ... ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| >>> tuple(map(float, result)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (-500.0, 100.0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| If the array contains NaNs, we'll use the ``nan`` version of of the numpy | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| functions by default. You can turn this off through the *nan* argument. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| >>> import numpy as np | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| >>> result = minmax((1, -10, 25, 2, 3, np.nan)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| >>> tuple(map(float, result)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (-10.0, 25.0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| >>> result = minmax((1, -10, 25, 2, 3, np.nan), nan=False) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| >>> tuple(map(float, result)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (nan, nan) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| If a more robust statistic is desired, you can use ``min_percentile`` and | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| or ``max_percentile`` to get the values at given percentiles instead of | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| the minimum and maximum. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| >>> import numpy as np | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| >>> result = minmax( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ... (1, -10, 25, 2, 3), min_percentile=2, max_percentile=98 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ... ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| >>> tuple(map(float, result)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (-9.12, 23.24) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| >>> result = minmax( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ... (1, -10, 25, 2, 3), min_percentile=0, max_percentile=100 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ... ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| >>> tuple(map(float, result)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (-10.0, 25.0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| arrays = [np.atleast_1d(i) for i in args] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # checks | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if not isinstance(min_percentile, (float, int)): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise TypeError( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f"Invalid 'min_percentile' of type '{type(min_percentile).__name__}'. Must be a float or int." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if not isinstance(max_percentile, (float, int)): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise TypeError( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f"Invalid 'max_percentile' of type '{type(max_percentile).__name__}'. Must be a float or int." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if not min_percentile <= max_percentile: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise ValueError( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f"'min_percentile' ({min_percentile}) must not be larger than 'max_percentile' ({max_percentile})." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if min_percentile < 0 or min_percentile > 100: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mdtanker marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise ValueError( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f"Invalid value for 'min_percentile' ({min_percentile}). Must be between 0 and 100." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if max_percentile < 0 or max_percentile > 100: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mdtanker marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise ValueError( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f"Invalid value for 'max_percentile' ({max_percentile}). Must be between 0 and 100." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # determine which functions to use | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if nan: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| npmin = np.nanmin | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| npmax = np.nanmax | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nppercentile = np.nanpercentile | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| elif not nan: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| npmin = np.min | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| npmax = np.max | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nppercentile = np.percentile | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise TypeError(f"The 'nan' parameter ({nan}) must be a boolean.") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mdtanker marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # get min value | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if min_percentile == 0: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| min_ = npmin([npmin(i) for i in arrays]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # get max value | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if max_percentile == 100: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| max_ = npmax([npmax(i) for i in arrays]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # calculate min, max or both percentiles | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if min_percentile != 0 or max_percentile != 100: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # concatenate values of all arrays | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| combined_array = np.concatenate([a.ravel() for a in arrays]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # if neither percentiles are defaults, calculate them together | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if min_percentile != 0 and max_percentile != 100: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| min_, max_ = nppercentile(combined_array, [min_percentile, max_percentile]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # only calculate min percentile | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| elif min_percentile != 0: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| min_ = nppercentile(combined_array, min_percentile) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # only calculate max percentile | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if max_percentile != 100: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| max_ = nppercentile(combined_array, max_percentile) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return min_, max_ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+367
to
+392
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we could simplify this logic a bit. What about this:
Suggested change
If any of the So, we would only use What do you think?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is a bit of time savings from only calculating one percentile and using min/max for the other. But maybe the time savings is not worth the extra code? At least that's how I interpreted the benchmarking results from below. The first uses min and max, with no percentiles, the second uses 1 and 99 percentiles, and the third uses min and 99 percentiles. As you can see, using 1 percentile and 1 min/max calculation is a bit fast than using 2 percentile calculations. What do you think? %timeit vd.minmax(a, min_percentile=0, max_percentile=100, nan=True)
%timeit vd.minmax(a, min_percentile=1, max_percentile=99, nan=True)
%timeit vd.minmax(a, min_percentile=0, max_percentile=99, nan=True)
>>>50.5 μs ± 2.56 μs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
>>>289 μs ± 26.5 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
>>>179 μs ± 3.93 μs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm I would have guessed that passing multiple percentiles would not impact the computation time that much. But nonetheless, those differences are not significant, so I think I would keep the code simpler. Do you agree? Even for a large array with 100 million elements, the difference is not very noticeable by users: import numpy as np
a = np.random.default_rng().uniform(size=100_000_000)
# benchmark np.min and np.percentile with a single value
%timeit np.min(a)
%timeit np.percentile(a, 90)# benchmark percentile with two values
%timeit np.percentile(a, [0, 90]) |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def make_xarray_grid( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| coordinates, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| data, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.