Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R, is there any function able to search and return only the first element that qualifies for something in a vector/list/matrix row/column?

Tags:

r

Following the title, for example, I want to get just the first even number in (1,4,5,2,7,45,8). I can do loop, I can use which(), but they seem not efficient enough. Do you have any better ideas?

Thank you!

like image 676
user2961927 Avatar asked Nov 30 '25 20:11

user2961927


2 Answers

Here's my first attempt with Rcpp. I don't really know C++, but this seems to work, and since it breaks after finding the first even number, and the explicit for loop runs in compiled code, it should be very fast.

>   library(Rcpp)
>   cppFunction('
+           int firstEven(IntegerVector x) {
+               int n = x.size();
+               for(int i = 0; i < n; ++i) {
+                   if (x[i] % 2 == 0) {
+                       return x[i];
+                   }
+               }
+           }'
+           )
>   firstEven(c(1,2,3,4))
[1] 2
> 

It is definitely a naive solution (e.g., no check if there isn't an even number in the vector).

like image 177
Clayton Stanley Avatar answered Dec 03 '25 12:12

Clayton Stanley


EDIT Results from timing the solutions for:

1) the vector approach: tst[tst %% 2 == 0][1]

2) firstEven (Rcpp)

3) for loop with break

4) match()

using two vectors, tst2 with first as even, tst with last as even:

tst <- c(rep(1, 10000000), 2)
tst2 <- c(2, rep(1, 10000000))

system.time results:

         test time
1     for.tst 8.11
2    for.tst2 0.00
3     cpp.tst 0.05
4    cpp.tst2 0.05
5  vector.tst 0.47
6 vector.tst2 0.47
7   match.tst 0.61
8  match.tst2 0.61

For loop has best case and worst case, the other two are the same in both cases, but using the Rcpp library is much faster.

For loop with a break statement to stop searching list

for (i in c(1,4,5,2,7,45,8)) {
    if (i %% 2 == 0) {
        print(i);
        break;
    }
}
like image 31
Rorschach Avatar answered Dec 03 '25 14:12

Rorschach



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!