However it only evaluates along a single axis and returns the index of the minimum value along a single row/column whereas I wish to evaluate the whole array and return the lowest value not the indices.
numpy.argmin does not by default evaluate along a single axis, the default is to evaluate along the flattened matrix and it returns the linear index in the flattened array; from the numpy docs that you linked:
By default, the index is into the flattened array, otherwise along the specified axis.
Either way, use numpy.amin or numpy.min to return the minimum value, or equivalently for an array arrname use arrname.min(). As you mentioned, numpy.argmin returns the index of the minimum value (of course, you can then use this index to return the minimum value by indexing your array with it). You could also flatten into a single dimension array with arrname.flatten() and pass that into the built-in min function.
The four following methods produce what you want.
import numpy as np
values = np.array([
[8,2,3,4,5,6],
[3,6,6,7,2,6],
[3,8,5,1,2,9],
[6,4,2,7,8,3]])
values.min() # = 1
np.min(values) # = 1
np.amin(values) # = 1
min(values.flatten()) # = 1
Answer from alkasm on Stack OverflowHowever it only evaluates along a single axis and returns the index of the minimum value along a single row/column whereas I wish to evaluate the whole array and return the lowest value not the indices.
numpy.argmin does not by default evaluate along a single axis, the default is to evaluate along the flattened matrix and it returns the linear index in the flattened array; from the numpy docs that you linked:
By default, the index is into the flattened array, otherwise along the specified axis.
Either way, use numpy.amin or numpy.min to return the minimum value, or equivalently for an array arrname use arrname.min(). As you mentioned, numpy.argmin returns the index of the minimum value (of course, you can then use this index to return the minimum value by indexing your array with it). You could also flatten into a single dimension array with arrname.flatten() and pass that into the built-in min function.
The four following methods produce what you want.
import numpy as np
values = np.array([
[8,2,3,4,5,6],
[3,6,6,7,2,6],
[3,8,5,1,2,9],
[6,4,2,7,8,3]])
values.min() # = 1
np.min(values) # = 1
np.amin(values) # = 1
min(values.flatten()) # = 1
Alternatively for a non-numpy solution:
>>> a = [[8,2,3,4,5,6],
... [3,6,6,7,2,6],
... [3,8,5,1,2,9],
... [6,4,2,7,8,3]]
>>> mymin = min([min(r) for r in a])
>>> mymin
1
Max of max numbers (map(max, numbers) yields 1, 2, 2, 3, 4):
>>> numbers = [0, 0, 1, 0, 0, 1], [0, 1, 0, 2, 0, 0], [0, 0, 2, 0, 0, 1], [0, 1, 0, 3, 0, 0], [0, 0, 0, 0, 4, 0]
>>> map(max, numbers)
<map object at 0x0000018E8FA237F0>
>>> list(map(max, numbers)) # max numbers from each sublist
[1, 2, 2, 3, 4]
>>> max(map(max, numbers)) # max of those max-numbers
4
Another way to solve this problem is by using function numpy.amax()
>>> import numpy as np
>>> arr = [0, 0, 1, 0, 0, 1] , [0, 1, 0, 2, 0, 0] , [0, 0, 2, 0, 0, 1] , [0, 1, 0, 3, 0, 0] , [0, 0, 0, 0, 4, 0]
>>> np.amax(arr)
I've seen some suggestions for pandas, which would also work well, but for something simple like this you may just want to use numpy:
import numpy as np
rainfall = np.loadtxt(filename, delimiter=',')
total = rainfall.sum()
print(f"The total rainfall for the year was {total:.0f}")
print(f"Overall Min: {rainfall.min()}")
print(f"Overall Max: {rainfall.max()}")
print("Weekly Sums:")
print(rainfall.sum(axis=1))
print("Weekly Mins:")
print(rainfall.min(axis=1))
Output:
The total rainfall for the year was 5344
Overall Min: 0.0
Overall Max: 30.0
Weekly Sums:
[ 89. 131. 91. 97. 68. 137. 113. 93. 115. 117. 128. 165. 89. 137.
58. 100. 96. 106. 80. 91. 60. 102. 126. 80. 111. 113. 135. 77.
100. 99. 129. 129. 118. 98. 93. 83. 99. 113. 85. 75. 100. 118.
76. 110. 91. 82. 137. 128. 107. 117. 68. 84.]
Weekly Mins:
[ 0. 3. 4. 0. 0. 8. 2. 0. 3. 5. 0. 20. 1. 6. 1. 7. 3. 0.
1. 1. 2. 2. 6. 2. 4. 3. 9. 4. 6. 2. 5. 11. 6. 5. 1. 1.
0. 3. 0. 5. 1. 2. 1. 0. 2. 1. 11. 3. 5. 3. 0. 0.]
from itertools import chain
array_max = max(chain(*arrayname))
array_min = min(chain(*arrayname))
Note that if you didn't convert the values to int first, then min and max will be the lowest and highest individual digits, because min and max will be checking character by character in the strings.
(edited to clarify what happens if you didn't convert to int)
np.where contains 3 inputs.
The first one is your condition [ False, True, True False ...]
The second and third inputs, are the possible values.
Thus, if the condition is True, grep the value of the second input
otherwise, take the value of the third input.
np.where(arr[:,0] > 12, np.max(arr, axis=1), np.min(arr, axis=1))
return: array([11, 16, 17, 12])
and if you need the sum, just add sum :) :
np.where(arr[:,0] > 12, np.max(arr, axis=1), np.min(arr, axis=1)).sum()
return: 56
another way to represent it is like:
[xv if c else yv for c, xv, yv in zip(condition, x, y)]
or just read the documentation: https://numpy.org/doc/stable/reference/generated/numpy.where.html :)
You are almost there. You can create a mask (whatever you desire, here is first element of each row greater than 12) and calculate your operation as below. This is easily extendable to multi-dimensional array by changing the axis in min/max and your desired mask condition:
mask=arr[:,0]>12
(arr.max(1)*mask + arr.min(1)*~mask).sum()
output:
56
Comparison:
def m1(arr):
mask=arr[:,0]>12
return (arr.max(1)*mask+arr.min(1)*~mask).sum()
#@Dieter's solution
def m2(arr):
return np.where(arr[:,0] > 12, np.max(arr, axis=1), np.min(arr, axis=1)).sum()
in_ = [np.random.randint(100, size=(n,n)) for n in [10,100,1000,10000]]
Runtime: m1 seems a tad faster, however, they converge to same performance in larger arrays.
alko's answer didn't work for me, so here's what I did:
import numpy as np
array = np.arange(15).reshape(5,3)
x,y = np.unravel_index(np.argmin(array),array.shape)
Seems like you need consecutive min along axis. For your first example:
>>> np.min(np.min(data, axis=1), axis=0)
array([ 0, 1])
For the second:
>>> np.min(np.min(data, axis=1), axis=0)
array([0, 3])
The same expression can be stated like this (with numpy >= 1.7, as pointed out by @Jaime)
>>> np.min(data, axis=(1, 0))
array([0, 3])
Is there a function in the numpy API that finds both max and min with only a single pass through the data?
No. At the time of this writing, there is no such function. (And yes, if there were such a function, its performance would be significantly better than calling numpy.amin() and numpy.amax() successively on a large array.)
You could use Numba, which is a NumPy-aware dynamic Python compiler using LLVM. The resulting implementation is pretty simple and clear:
import numpy
import numba
@numba.jit
def minmax(x):
maximum = x[0]
minimum = x[0]
for i in x[1:]:
if i > maximum:
maximum = i
elif i < minimum:
minimum = i
return (minimum, maximum)
numpy.random.seed(1)
x = numpy.random.rand(1000000)
print(minmax(x) == (x.min(), x.max()))
It should also be faster than a Numpy's min() & max() implementation. And all without having to write a single C/Fortran line of code.
Do your own performance tests, as it is always dependent on your architecture, your data, your package versions...
I'm just putting @gtlambert's comment into an answer, since it's probably the best choice. Use the array.min function
x = array([[ 8, 31],
[96, 97],
[26, 31],
[81, 70],
[47, 97],
[95, 84],
[11, 93],
[31, 77],
[25, 45],
[79, 22]])
In [6]: x.min(axis=0)
Out[6]: array([ 8, 22])
Probably not the most efficient, but...
left = np.array([])
right = np.array([])
for n in aaa:
left = np.append(left,n[0])
right = np.append(right,n[1])
sol = [np.min(left), np.min(right)]