A quick way in R to do two nested loops

I need to distinguish any two elements from two vectors. If A<-c(1,2)and B<-c(3,4)then my result Rshould be c(3-1,3-2,4-1,4-2).

Using this snippet

myfunction <- function(N)
{
  A = runif(N)
  B = runif(N)
  R = c()
  for(a in A){
    for(b in B){
      R=c(b-a,R)
    }
  }
  R
}
print(system.time(result <- myfunction(300)))

I get this time

   user  system elapsed 
  14.27    0.01   14.39 

Is there a faster way to do this?

+4
source share
3 answers

The fastest basic solution is to use outer:

as.vector(outer(B,A,"-"))

To my own surprise, map2_dblactually quite quickly than outer:

Not to my surprise, map2_dblit seems faster, but this is because it does not calculate every combination of the values ​​in A and B:

      test elapsed relative
3 CP(A, B)    7.54   47.125 # using expand.grid
2 JL(A, B)    0.16    1.000 # using map2_dbl
1 JM(A, B)    3.13   19.563 # using outer

But:

> A <- 1:3
> B <- 3:1
> JL(A,B)
[1] -2  0  2
> JM(A,B)
[1]  2  1  0  1  0 -1  0 -1 -2

1000 100 . , :

  • for R , , , , , C . , .
  • "" . , R , R . . , .

:

library(tidyverse)

JM <- function(A,B){
  as.vector(outer(B,A,"-"))
}

JL <- function(A,B){
  map2_dbl(.x = A, 
           .y = B, 
           .f = ~ c(.x - .y))
}

CP <- function(A,B){
  as.data.frame(expand.grid(A,B)) %>%
    mutate(Var3 = Var2-Var1)
}

library(rbenchmark)

A <- runif(1000)
B <- runif(1000)

benchmark(JM(A,B),
          JL(A,B),
          CP(A,B),
          replications = 100,
          columns = c("test","elapsed","relative"))
+5

expand.grid :

A <- runif(300)
B <- runif(300)

library(dplyr)
R <- as.data.frame(expand.grid(A,B)) %>%
       mutate(Var3 = Var2-Var1)  

5 :

      Var1     Var2          Var3
1 0.8516676 0.325261 -0.5264066246
2 0.2126453 0.325261  0.1126156694
3 0.5394620 0.325261 -0.2142010126
4 0.1364876 0.325261  0.1887734290
5 0.3248651 0.325261  0.0003958747 

:

user  system elapsed 
0.02    0.00    0.02

:

 user  system elapsed 
42.39    0.43   42.90    
+2

Usage purrr::map2:

library(tidyverse)

N = 300
A = runif(N)
B = runif(N)
R = c()

print(
  system.time(
    result <- map(
      .x = A,
      .f = ~ c(.x - B)) %>% unlist
  )
)

Time:

 user  system elapsed 
 0.02       0    0.02 

If I got your attention now, check out this repo for a nice walkthrough purrr.

-4
source

Source: https://habr.com/ru/post/1681349/


All Articles