Let's start by importing NumPy and creating an array to use to explore `np.amax()`
You can read more about using `np.random.default_rng()` to create a `Generator` instance, which is NumPy's preferred way of creating random numbers, in the quoted thread
I'm using the `seed` parameter in `default_rng()`. This ensures I get the same numbers each time I run the code which makes it easier to explore different ways of using the same function
You can remove this to get different random numbers each time you run the code
/4
You cannot use the built-in `max()` function directly on the array `numbers` because it has more than one dimension
If you try to call `max(numbers)`, you'll get a `ValueError`
The built-in `max()` will work on one-dimensional NumPy arrays
/5
So, we'll need to use NumPy's version of this function
Although you can use `np.max()`, this function is an alias for `np.amax()`, so I'll use `np.amax()` directly
This also reminds us of the differences between the built-in and NumPy versions!
/6
The largest number in the 2D array is 87
By default, `np.amax()` finds the maximum across the whole array. It flattens the array to find the maximum value
/7
However, you may be interested in finding the maximum value in each column
You can use the `axis` parameter to choose which axis to go along when looking for the maximum
/8
The array has shape `(3, 5)`. Therefore `axis=0` represents the dimension with a value of 3
The output is a 1D array of length 5 where each value is the maximum value in each column of the original array `numbers`
/9
If you want to find the maximum in each row, then you can use `axis=1`
If you can't quite remember which axis you need to get the functions to operate along rows or columns, just use trial and error. I often do this!
/10
The output is now a 1D array of length 3, the same as the number of rows in the original array
The values are the maximum in each row
/11
The result of `np.amax()` for the 2D array we're using is a 1D array when using a single axis, as in the previous two examples
You may need to keep the same number of dimensions in your output. In this case, you can use the `keepdims` parameter
/12
The output from `np.amax()` is now also a 2D array. You can see this from the number of pairs of square brackets you see in the output
You can also access the `shape` attribute which will show you that the output has shape `(3, 1)` It's a 2D array with 3 rows and 1 column
/13
The values are the same as the ones you got when you didn't set `keepdims=True` but the shape of the output array is different
This can be useful if you want to perform operations between the original array and the `np.amax()` result since they can be broadcast together
/14
If you're not familiar with broadcasting rules in NumPy, you can have a look at this thread from a while ago:
`initial` sets a minimum value for `np.amax()`. Therefore, when looking for the maximum value, the initial value is also thrown into the mix, as seen in this example
/17
The array's maximum value is `87` which is smaller than the argument you assigned to `initial`, which is `95`
Therefore, `np.amax()` returns 95 in this case
The array's maximum value is returned if it's larger than `initial`
/18
You can also select which elements in the array to consider when looking for the maximum if you don't want to consider all of them
You can use the `where` parameter for this:
/19
We've used an array with the same shape as the original array to assign to `where`. This array contains Boolean values
Only the elements in the original array which match a `True` value in the `where` array are considered when looking for the maximum
/20
The actual highest value of `87` matches a `False`, so it's not included when looking for the maximum
Therefore, `np.amax()` returns 82, which is the highest value from those which match a `True` in `where`
/21
You may have noted I've also used `initial` in this call and set it to -1
When you use the `where` mask, you need to set an `initial` value to serve as a default in case no elements are included
/22
If you leave this out, you'll get a `ValueError` asking you to use `initial`
You'll see why this is needed in one of the last examples in this thread
/23
Let's add the `axis` parameter again to see what happens:
/24
`axis=1` looks for the maximum along rows, but the elements in each row are masked by the `where` mask which is now a 1D array
Therefore, only the first, fourth, and fifth elements in each row are considered when looking for the maximum
/25
Let's use `axis=0` to see what the output looks like
/26
The maximum values in the first, fourth, and fifth columns are shown in the output
However, since the second and third elements in `where` are `False`, none of the values in these columns are used
/27
This means that these columns don't have a maximum value
This is where the default value you set with the `initial` parameter kicks in
/28
This leaves one more parameter: `out`
This parameter allows you to place the result of `np.amax()` in another pre-existing array
In this example, we first create a `(3, 1)` array of zeros called `result` and place the output of `np.amax()` in this array
/29
Note that I'm printing the array `result` and not the value returned directly by `np.amax()` in this example
`result` is a 3 x 1 array and we're using `keepdims=True` which means that the output from `np.amax()` also has shape `(3, 1)`
/30
Let's look at one final example using the `out` parameter
In this example, you create `result` as a 3 x 3 array of zeros and you want to place the output from `np.amax()` in the first column of `result`
/31
We're no longer setting `keepdims=True` so that the output is 1D
This allows us to place it in the first column of `result` using `result[:, 0]` as the `out` argument
/32
You can spend a bit more time playing with all the options in `np.amax()`, and then you can move to 3 or more dimensional-arrays too. Just for fun!
/33
• • •
Missing some Tweet in this thread? You can try to
force a refresh
You're creating an instance of the `datetime.datetime` class when you use `now()`
As most objects, this instance will have some data attributes (you may call them instance variables). These are the attributes that store data (that is the variables linked to the instance)
/2
You can see what data attributes `datetime.datetime` has in the docs: