Die schnellste Basislösung die Verwendung von outer
ist:
as.vector(outer(B,A,"-"))
Zu meiner eigenen Überraschung,
map2_dbl
ist eigentlich ziemlich viel schneller als
outer
:
Nicht zu meiner Überraschung, map2_dbl
scheint schneller , aber das liegt daran, dass nicht jede Kombination der Werte in A und B berechnet wird:
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
Aber:
> 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
Dies ist für zwei Vektoren der Länge 1000 und mit 100 Replikationen. Ich habe nicht Ihre eigene Lösung enthalten, da, dass man aus zwei Gründen unglaublich langsam ist:
for
Schleifen in R sind um einiges schneller als in den alten Tagen, aber immer noch nicht so optimal wie Funktionen verwenden, die ihre Schleifen codiert in C
oder gleichwertig. Das ist der Fall für die Funktionen, die hier im getesteten Code verwendet werden.
- "wachsen" Sie Ihr Ergebnisobjekt. Jede Schleife durch den Code, die
R
wird einen Wert größer, so dass R nach einem neuen Platz im Speicher suchen muss, um es zu speichern. Das ist der größte Engpass in Ihrem Code.Versuchen Sie, diese Art von Konstrukt um jeden Preis zu vermeiden, weil es eine der wichtigsten Ursachen für schrecklich langsamen Code ist.
Der Benchmark-Code:
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"))
'äußeren (A, B,' -') '? Siehe [hier] (https://stackoverflow.com/a/29950048/680068), Zitate werden durcheinander gebracht. – zx8754
nice @ zx8754, hätte nicht gedacht, dass die BaseR Lösung wäre so schnell! – JanLauGe
@ JanLauGe das ist R, alles ist ein Vektor. – zx8754