user9798936
user9798936

Reputation:

R: how to calculate element-wise arg-min from a list of matrices?

Suppose I have a list of matrices. Suppose further I have found the smallest values by the column. Here is my last question

I really need to know from which matrix each smallest value is selected. My original function is very complicated. Therefore, I provided a simple example. I have one idea and really do not know to implement it correctly in R.

My idea is:

Suppose that [i,j] is the elements of the matrix. Then,

if(d[[1]][i,j] < d[[2]][i,j]){
d[[1]][i,j] <– "x"
}else { d[[2]][i,j] <– "z"}

So, I would like to sign the name of the matrix that corresponds to each smallest value. Then, store the names in a separate matrix. So, then I can see the values in one matrix and their corresponding names (from where they come from) in another matrix

For example,

y <- c(3,2,4,5,6, 4,5,5,6,7)
x[lower.tri(x,diag=F)] <- y
> x
     [,1] [,2] [,3] [,4] [,5]
[1,]    0    0    0    0    0
[2,]    3    0    0    0    0
[3,]    2    6    0    0    0
[4,]    4    4    5    0    0
[5,]    5    5    6    7    0



k <- c(1,4,5,2,5,-4,4,4,4,5)
z[lower.tri(z,diag=F)] <- k
> z
     [,1] [,2] [,3] [,4] [,5]
[1,]    0    0    0    0    0
[2,]    1    0    0    0    0
[3,]    4    5    0    0    0
[4,]    5   -4    4    0    0
[5,]    2    4    4    5    0



 d <- list(z, x)

Then:

do.call(pmin, d) (answered by @akrun)

Then, I will only get the matrix with smallest values. I would like to know where each value is come from?

Any idea or help, please?

Upvotes: 1

Views: 1745

Answers (2)

akrun
akrun

Reputation: 887058

Or another option would be to convert it to a 3D array and use apply with which.min

apply(array(unlist(d), c(5, 5, 2)), c(1, 2), which.min)

Or with pmap from purrr

library(purrr)
pmap_int(d, ~ which.min(c(...))) %>%
       array(., dim(x))

Upvotes: 0

Alexis
Alexis

Reputation: 5059

You can use Map and do.call to create your own functions that will be applied element-wise to a list of inputs, in your case a list of matrices.

pwhich.min <- function(...) {
  which.min(c(...)) # which.min takes a single vector as input
}

di <- unlist(do.call(Map, c(list(f = pwhich.min), d)))
dim(di) <- dim(x) # take dimension from one of the inputs
di

     [,1] [,2] [,3] [,4] [,5]
[1,]    1    1    1    1    1
[2,]    2    1    1    1    1
[3,]    1    2    1    1    1
[4,]    1    2    2    1    1
[5,]    2    2    2    2    1

EDIT:

To elaborate, you could do something like Map(f = min, z, x) to apply min to each pair of values in z and x, although in that case min already supports arbitrary amount of inputs through an ellipsis (...).

By contrast, which.min only takes a single vector as input, so you need a wrapper with an ellipsis that combines all values into a vector (pwhich.min above).

Since you may want to have more than two matrices, you can put them all in a list, and use do.call to put each element in the list as a parameter to the function you specify in f.

Upvotes: 2

Related Questions