fastest way to get Min from every column in a matrix?
Here is one that is faster on square and wide matrices. It uses pmin
on the rows of the matrix. (If you know a faster way of splitting the matrix into its rows, please feel free to edit)
do.call(pmin, lapply(1:nrow(mat), function(i)mat[i,]))
Using the same benchmark as @RicardoSaporta:
$`Square Matrix`
test elapsed relative
3 pmin.on.rows 1.370 1.000
1 apl 1.455 1.062
2 cmin 2.075 1.515
$`Wide Matrix`
test elapsed relative
3 pmin.on.rows 0.926 1.000
2 cmin 2.302 2.486
1 apl 5.058 5.462
$`Tall Matrix`
test elapsed relative
1 apl 1.175 1.000
2 cmin 2.126 1.809
3 pmin.on.rows 5.813 4.947
Fastest way to find the maximum minimum value of two 'connected' matrices
Perhaps you could re-evaluate how you look at the problem in context of what min and max actually do. Say you have the following concrete example:
>>> np.random.seed(1)
>>> print(A := np.random.randint(10, size=(4, 5)))
[[5 8 9 5 0]
[0 1 7 6 9]
[2 4 5 2 4]
[2 4 7 7 9]]
>>> print(B := np.random.randint(10, size=(5, 3)))
[[1 7 0]
[6 9 9]
[7 6 9]
[1 0 1]
[8 8 3]]
You are looking for a pair of numbers in A
and B
such that the column in A
is the same as the row of B
, and the you get the maximum smaller number.
For any set of numbers, the largest pairwise minimum happens when you take the two largest numbers. You are therefore looking for the max in each column of A
, row of B
, the minimum of those pairs, and then the maximum of that. Here is a relatively simple formulation of the solution:
candidate_i = A.argmax(axis=0)
candidate_k = B.argmax(axis=1)
j = np.minimum(A[candidate_i, np.arange(A.shape[1])], B[np.arange(B.shape[0]), candidate_k]).argmax()
i = candidate_i[j]
k = candidate_k[j]
And indeed, you see that
>>> i, j, k
(0, 2, 2)
>>> A[i, j]
9
>>> B[j, k]
9
If there are collisions, argmax
will always pick the first option.
Minimum value in each row and each column of a matrix - Python
Use numpy.
>>> import numpy as np
>>> matrix =[[12,34,28,16],
... [13,32,36,12],
... [15,32,32,14],
... [11,33,36,10]]
>>> np.min(matrix, axis=1) # computes minimum in each row
array([12, 12, 14, 10])
>>> np.min(matrix, axis=0) # computes minimum in each column
array([11, 32, 28, 10])
Fastest way to find the maximum minimum value of three 'connected' matrices
We can either brute force it using numpy
broadcasting or try a bit of smart branch cutting:
import numpy as np
def bf(A,B,C):
I,J = A.shape
J,K = B.shape
return np.unravel_index((np.minimum(np.minimum(A[:,:,None],C[:,None,:]),B[None,:,:])).argmax(),(I,J,K))
def cut(A,B,C):
gmx = min(A.min(),B.min(),C.min())
I,J = A.shape
J,K = B.shape
Y,X = np.unravel_index(A.argsort(axis=None)[::-1],A.shape)
for y,x in zip(Y,X):
if A[y,x] <= gmx:
return gamx
curr = np.minimum(B[x,:],C[y,:])
camx = curr.argmax()
cmx = curr[camx]
if cmx >= A[y,x]:
return y,x,camx
if gmx < cmx:
gmx = cmx
gamx = y,x,camx
return gamx
from timeit import timeit
I = 100
J = 150
K = 200
for rep in range(4):
print("trial",rep+1)
A = np.random.rand(I, J)
B = np.random.rand(J, K)
C = np.random.rand(I, K)
print("results identical",cut(A,B,C)==bf(A,B,C))
print("brute force",timeit(lambda:bf(A,B,C),number=2)*500,"ms")
print("branch cut",timeit(lambda:cut(A,B,C),number=10)*100,"ms")
It turns out that at the given sizes branch cutting is well worth it:
trial 1
results identical True
brute force 169.74265850149095 ms
branch cut 1.951422297861427 ms
trial 2
results identical True
brute force 180.37619898677804 ms
branch cut 2.1000938024371862 ms
trial 3
results identical True
brute force 181.6371419990901 ms
branch cut 1.999850495485589 ms
trial 4
results identical True
brute force 217.75578951928765 ms
branch cut 1.5871295996475965 ms
How does the branch cutting work?
We pick one array (A, say) and sort it from largest to smallest. We then go through the array one by one comparing each value to the appropriate values from the other arrays and keeping track of the running maximum of minima. As soon as the maximum is no smaller than the remaining values in A we are done. As this will typically happen rather soonish we get a huge saving.
Fastest way to find minimum value in each column
If an array of size X is not sorted or structured in some known special way, then cost for finding element y
in it must be equal to X, because you cant skip any element in X (the skipped one can be the solution).
The order of searching does not matter either. If you split it and divide and conquer etc., still the element y
can be the last one you visit.
Therefore if you have an array of size n*logn
, the lowest possible complexity is Omega(n* log n)
.
Find the maximum and minimum value of every column and then find the maximum and minimum value of every row
Figured it out.
Minimum and maximum of every column:
apply(a,2,min)
apply(a,2,max)
Minimum and maximum of every row:
apply(a,1,min)
apply(a,1,max)
Found the information here http://www.personality-project.org/r/r.commands.html
Fast way to find index of max/min element in Nth column of matrix
A simple solution would be to loop over the array and store the min/max values in a temporary variable.
function minMax (arr, n) { let min=Infinity, max=0; for (const _arr of arr) { const x = _arr[n]; if (x < min) min = x; if (x > max) max = x; } return [min, max];}
function minMaxIndex (arr, n) { let min=Infinity, max=0, minIndex, maxIndex; for (let i=0; i < arr.length; i++) { const x = arr[i][n]; if (x < min) { min = x; minIndex = i; } if (x > max) { max = x; maxIndex = i; } } return [minIndex, maxIndex];}
console.log (minMax(a, 0))console.log (minMaxIndex(a, 0))
<script>a = [ [22,23], [74,1], [21,33], [32,84], [11,31], [1,49], [7,8], [11,11], [99,68], [52,20]];</script>
Find min value and index of the value in a matrix column after column
np.amin
or np.min
returns the min values along an axis
np.amin(arr2D, axis=0)
Out:
array([ 1, 5, 4, -3])
np.argmin
returns the indices
np.argmin(arr2D, axis=0)
Out:
array([4, 3, 4, 5])
To get the desired output you can use np.vstack
and transpose the array
np.vstack([np.amin(arr2D, axis=0), np.argmin(arr2D, axis=0)]).T
Out:
array([[ 1, 4],
[ 5, 3],
[ 4, 4],
[-3, 5]])
Return Index of Minimum Row for Each Column of Matrix
If we need column wise index use apply
with MARGIN=2
and apply the which.min
apply(m1, 2, which.min)
#[1] 3 3
If 1 column at a time is needed:
apply(as.matrix(m1[,1, drop = FALSE]), 2, which.min)
If we check ?Extract
, the default usage is
x[i, j, ... , drop = TRUE]
drop - For matrices and arrays. If TRUE the result is coerced to the lowest possible dimension (see the examples). This only works for extracting elements, not for the replacement. See drop for further details.
To avoid getting dimensions dropped, use drop = FALSE
If we need the min values of each row
do.call(pmin, as.data.frame(m1))
Or
apply(m1, 2, min)
Or
library(matrixStats)
rowMins(m1)
data
m1 <- matrix(6:1,nrow=3,ncol=2)
Related Topics
Unpacking and Merging Lists in a Column in Data.Frame
Ggplot2 Wind Time Series with Arrows/Vectors
How to Check If Each Element in a Vector Is Integer or Not in R
Split a File Path into Folder Names Vector
How to Download a Large Binary File with Rcurl *After* Server Authentication
Automatically Detect Date Columns When Reading a File into a Data.Frame
Add Columns to a Reactive Data Frame in Shiny and Update Them
How to Log an R Session to a File
How to Use the Function Curve in [R] to Graph a Normal Curve
Is There a Fast Parser for Date
Different Y-Limits on Ggplot Facet Grid Bar Graph
Plot Table Objects with Ggplot
Nan Is Removed When Using Na.Rm=True
Gadm-Maps Cross-Country Comparison Graphics
How to Run a Function Every Second