Reputation: 591
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
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
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
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