214

numpy has three different functions which seem like they can be used for the same things --- except that numpy.maximum can only be used element-wise, while numpy.max and numpy.amax can be used on particular axes, or all elements. Why is there more than just numpy.max? Is there some subtlety to this in performance?

(Similarly for min vs. amin vs. minimum)

Alex Riley
  • 169,130
  • 45
  • 262
  • 238
DilithiumMatrix
  • 17,795
  • 22
  • 77
  • 119

4 Answers4

252

np.max is just an alias for np.amax. This function only works on a single input array and finds the value of maximum element in that entire array (returning a scalar). Alternatively, it takes an axis argument and will find the maximum value along an axis of the input array (returning a new array).

>>> a = np.array([[0, 1, 6],
                  [2, 4, 1]])
>>> np.max(a)
6
>>> np.max(a, axis=0) # max of each column
array([2, 4, 6])

The default behaviour of np.maximum is to take two arrays and compute their element-wise maximum. Here, 'compatible' means that one array can be broadcast to the other. For example:

>>> b = np.array([3, 6, 1])
>>> c = np.array([4, 2, 9])
>>> np.maximum(b, c)
array([4, 6, 9])

But np.maximum is also a universal function which means that it has other features and methods which come in useful when working with multidimensional arrays. For example you can compute the cumulative maximum over an array (or a particular axis of the array):

>>> d = np.array([2, 0, 3, -4, -2, 7, 9])
>>> np.maximum.accumulate(d)
array([2, 2, 3, 3, 3, 7, 9])

This is not possible with np.max.

You can make np.maximum imitate np.max to a certain extent when using np.maximum.reduce:

>>> np.maximum.reduce(d)
9
>>> np.max(d)
9

Basic testing suggests the two approaches are comparable in performance; and they should be, as np.max() actually calls np.maximum.reduce to do the computation.

Alex Riley
  • 169,130
  • 45
  • 262
  • 238
  • 1
    Thanks. Obviously one can use `amax` for the same (root) purpose as `maximum`, i.e. with `numpy.amax([a1, a2], axis=0)` --- but is this not as optimized for this behavior as `numpy.maximum`? Similarly, do the added niceties of `numpy.amax` (e.g. the `axis` parameter) preclude it from being a `ufunc`? – DilithiumMatrix Nov 06 '15 at 15:26
  • 2
    That's right, `amax` is not optimised for of element-wise comparison in this - any input will need to be a Numpy array, so that list would be converted before the operation ran (assuming that the two shapes were the same). The docs for `amax` specifically say that `maximum` is faster here. – Alex Riley Nov 06 '15 at 15:31
  • On the second question: I guess `amax` *could* be made into a ufunc, although the main purpose of ufuncs is to allow operations to be broadcast between arrays. There seems little need to make `max` a unary ufunc. I think `amax` existed before ufuncs were really a thing (it came from numeric, NumPy's parent) so is also kept for posterity. – Alex Riley Nov 06 '15 at 15:36
  • 1
    [Here](https://docs.scipy.org/doc/numpy/reference/ufuncs.html) `maximum.reduce` is preferred for performance: `The Python function max() will find the maximum over a one-dimensional array, but it will do so using a slower sequence interface. The reduce method of the maximum ufunc is much faster. Also, the max() method will not give answers you might expect for arrays with greater than one dimension.` [...] – Tom Hale Feb 15 '19 at 07:06
  • 1
    @TomHale: I think that documentation is referring to the Python built in `max()` function, rather than `numpy.max()`, but it is definitely worth pointing out that the Python `max()` is slower. – Alex Riley Feb 16 '19 at 11:15
  • Isn't there any way to detect which functions are aliases of others? It seems rather ridiculous that Python is so opaque that people are forced to do all sorts of benchmarks to attempt to distinguish the myriad identically named functions floating about. – berniethejet Dec 29 '22 at 21:37
26

You've already stated why np.maximum is different - it returns an array that is the element-wise maximum between two arrays.

As for np.amax and np.max: they both call the same function - np.max is just an alias for np.amax, and they compute the maximum of all elements in an array, or along an axis of an array.

In [1]: import numpy as np

In [2]: np.amax
Out[2]: <function numpy.core.fromnumeric.amax>

In [3]: np.max
Out[3]: <function numpy.core.fromnumeric.amax>
tmdavison
  • 64,360
  • 12
  • 187
  • 165
  • 3
    I feel stupid now, I was doing `from numpy import max as np_max` just to avoid conflict with the generic `max` all the time while I could have just used `amax` *hides*. – Bas Jansen Aug 31 '18 at 11:53
14

For completeness, in Numpy there are four maximum related functions. They fall into two different categories:

  • np.amax/np.max, np.nanmax: for single array order statistics
  • and np.maximum, np.fmax: for element-wise comparison of two arrays

I. For single array order statistics

NaNs propagator np.amax/np.max and its NaN ignorant counterpart np.nanmax.

  • np.max is just an alias of np.amax, so they are considered as one function.

    >>> np.max.__name__
    'amax'
    >>> np.max is np.amax
    True
    
  • np.max propagates NaNs while np.nanmax ignores NaNs.

    >>> np.max([np.nan, 3.14, -1])
    nan
    >>> np.nanmax([np.nan, 3.14, -1])
    3.14
    

II. For element-wise comparison of two arrays

NaNs propagator np.maximum and its NaNs ignorant counterpart np.fmax.

  • Both functions require two arrays as the first two positional args to compare with.

    # x1 and x2 must be the same shape or can be broadcast
    np.maximum(x1, x2, /, ...);
    np.fmax(x1, x2, /, ...)
    
  • np.maximum propagates NaNs while np.fmax ignores NaNs.

    >>> np.maximum([np.nan, 3.14, 0], [np.NINF, np.nan, 2.72])
    array([ nan,  nan, 2.72])
    >>> np.fmax([np.nan, 3.14, 0], [np.NINF, np.nan, 2.72])
    array([-inf, 3.14, 2.72])
    
  • The element-wise functions are np.ufunc(Universal Function), which means they have some special properties that normal Numpy function don't have.

    >>> type(np.maximum)
    <class 'numpy.ufunc'>
    >>> type(np.fmax)
    <class 'numpy.ufunc'>
    >>> #---------------#
    >>> type(np.max)
    <class 'function'>
    >>> type(np.nanmax)
    <class 'function'>
    

And finally, the same rules apply to the four minimum related functions:

  • np.amin/np.min, np.nanmin;
  • and np.minimum, np.fmin.
YaOzI
  • 16,128
  • 9
  • 76
  • 72
3

np.maximum not only compares elementwise but also compares array elementwise with single value

>>>np.maximum([23, 14, 16, 20, 25], 18)
array([23, 18, 18, 20, 25])
shivaraj karki
  • 139
  • 1
  • 8