mrkb80
mrkb80

Reputation: 591

min value(greater than 0) from column combined with row operation

I am trying to get the minimum value (greater than 0) from a column in a matrix and then use the row number where that minimum occurred to calculate a value that gets applied (as a formula) to all rows below the minimum row(identified previously).

Let me demonstrate with an example: If I define x as:

x<-rbind(c(0, 0, 0), c(0,0,3), c(0,3,5))

such that x is:

     [,1] [,2] [,3]
[1,]    0    0    0
[2,]    0    0    3
[3,]    0    3    5

then I would like to identify that column 1 has no minimum, column 2 has a minimum at index 3, and column 3 has an minimum at index 2.

So, I created the following attempt at creating a vector of minimums:

min<-apply(x,2,function (v) min(which(v>0), na.rm = TRUE))

This gives me a warning:

Warning message:
In min(which(v > 0), na.rm = TRUE) :
  no non-missing arguments to min; returning Inf

(problem 1): Which I do not know how to avoid.

(problem 2): I now need to take the results of the minimum (where one exists) and calculate the value of a function based on the value of the vector min, as well as using the index of the vector min to select a value from a different matrix st This I have played around a bit with, without resorting to loops, am unsure of how to do.

Going back to the example, the first value in min is Inf, so my vector calc.results gets 0, the next value in min is 3, so from matrix st I would like to select the 3rd row in the 2nd column (3) and then use this value to calculate the result for the 2nd column in calc.results, etc. After the operation is complete calc.results would look something like (for example simplicity, nothing is done with the value from st):

[1] 0 3 3

I then need to apply calc.results back to matrix st by subtracting the value of calc.results only after I have reached the row identified earlier in min (with the index of min equaling the column of st) All other rows are left untouched.

In the example, the final result would look something like this:

     [,1] [,2] [,3]
[1,]    0    0    0
[2,]    0    0    0
[3,]    0    0    2

since in the 2nd column, the value of min was 3, and the value of calc.results was 3 in the 2nd column, st has 3 subtracted in 2nd column only in row 3, etc (note that the fact, the columns become zeroed out is a product of this example and not generally true).

Upvotes: 3

Views: 5907

Answers (3)

A5C1D2H2I1M1N2O1R2T1
A5C1D2H2I1M1N2O1R2T1

Reputation: 193497

It sounds like you're trying to do something like this:

apply(x, 2, function(y) { y[y > 0] <- (y[y > 0] - min(y[y > 0])); y })
     [,1] [,2] [,3]
[1,]    0    0    0
[2,]    0    0    0
[3,]    0    0    2

Upvotes: 2

Ricardo Saporta
Ricardo Saporta

Reputation: 55340

problem(1)

the warning is due to the fact that you are taking min of a non-number, namely integer(0)

# try this to see the warning clearly: 
min(integer(0))

# try this to see where you are getting integer(0)
apply(x,2,function (v) which(v>0))

To avoid the warning, you can add an if-statement in function(v) such as:

apply(x, 2, function (v) min(ifelse(any(v>0), which(v>0), 0), na.rm = TRUE))

however, keep in mind that it is just a warning, and so long as you are aware of what specifically is causing it, you do not need to worry much about it.

Upvotes: 0

Gary Weissman
Gary Weissman

Reputation: 3627

problem(1): You can at least identify the columns without any min, then remove them later as needed.

min <- apply(x,2,function (v) ifelse(max(v)==0, NA , min(which(v>0), na.rm = TRUE)))

Upvotes: 0

Related Questions