Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting index of first occurrence of a value in every column of a matrix

Tags:

r

If I have a single vector, I can get the 1st occurrence which is below a value:

test <- c(0.5,0.8,0.1,0.08,0.06,0.04)
which(test<0.1)[1]    

which correctly gives the answer as 4. However, how do I get the first occurrence within each column of a matrix, such as the furst occurrence below 5 in the following 2 column matrix:

test2 <- matrix(c(5,8,3,4,7,5,6,2),ncol=2)

Using apply with which returns a list:

> apply(test2<5,2,which)
[[1]]
[1] 3 4

[[2]]
[1] 4

while using apply with which.min returns 1 for all columns:

> apply(test2<5,2,which.min)
[1] 1 1

whereas, what I want should just return [1] 3 4 - am I missing something obvious?

like image 248
ChrisW Avatar asked May 28 '12 18:05

ChrisW


4 Answers

Here's another answer. Assuming you mean test2 where you write test3, note that 'test2<5' is a logical vector. The minimum value will be FALSE. The maximum value (TRUE) is what you want:

> apply(test2<5,2,which.max)
[1] 3 4

Note that this is not correct if the maximum value is not TRUE.

like image 55
Matthew Lundberg Avatar answered Nov 02 '22 14:11

Matthew Lundberg


Try this:

test2 <- matrix(c(5,8,3,4,7,5,6,2),ncol=2)
> test2
     [,1] [,2]
[1,]    5    7
[2,]    8    5
[3,]    3    6
[4,]    4    2
> foo <- function(x){which(x < 5)[1]}
> apply(test2,2,foo)

The key here being that you take the piece that you know works on a single vector, and simply wrap it in a function. apply will, well, apply that function to each column.

like image 41
joran Avatar answered Nov 02 '22 15:11

joran


Because I just stumbled upon this, here's another solution:

max.col(t(test2 < 5), "first")
like image 4
adibender Avatar answered Nov 02 '22 16:11

adibender


As noted by Matthew, which.max does not return the correct value if there's no value <5 in a column (it returns 1, whereas the correct value is "nothing"). The match function is nice to handle this case:

> test2 <- matrix(c(5,8,3,4, 7,5,6,7), ncol=2)
> apply(test2<5, 2, which.max)
[1] 3 1
> apply(test2<5, 2, function(x) match(TRUE, x))
[1]  3 NA
like image 1
Stéphane Laurent Avatar answered Nov 02 '22 14:11

Stéphane Laurent