2017-05-31 5 views
3

Gegeben ein Vektor v <- c(1, 10, 22) und eine konstante natürliche Zahl sagen c <- 3 wie kann ich v mit Ganzzahlen in einem Fenster der Größe c erweitern. So würde der Vektor wird w (dh 1 expandiert drei ganze Zahlen zu jeder Seite, die ganzen Zahlen -2, -1, 0, 1, 2, 3, 4):Erweitern numerische Vektorelemente mit Konstante (natürliche Zahl)

> w 
[1] -2 -1 0 1 2 3 4 7 8 9 10 11 12 13 19 20 21 22 23 24 25 
+1

'c (t (sapply (-3: 3, \ '+ \', v))) ' –

Antwort

2

Wir sapply verwenden können

c(sapply(v, function(x) (x-c):(x+c))) 
#[1] -2 -1 0 1 2 3 4 7 8 9 10 11 12 13 19 20 21 22 23 24 25 

Oder Map

unlist(Map(`:`, v-c, v+c)) 
+1

Das ist wunderbar und prägnant. Im zweiten wenden Sie die Funktion ':' auf die zwei Argumente an (die Grenzen meiner Reichweite)? – user3375672

+1

@ user3375672 'Map' nimmt entsprechende Elemente aus den Vektoren' vc' und 'v + c' und gibt sie an': 'um die Folge zu erhalten – akrun

2

Mit mapply:

c(mapply(seq, v-c, v+c)) 

#[1] -2 -1 0 1 2 3 4 7 8 9 10 11 12 13 19 20 21 22 23 24 25 
5

Ein weiterer Ansatz ist

c(t(sapply(-c:c, `+`, v))) 
#[1] -2 -1 0 1 2 3 4 7 8 9 10 11 12 13 19 20 21 22 23 24 25 

Und dies ist effizienter für große v-Vektoren, weil die sapply Schleife wiederholt nur über -c:c statt jedes Element v. dies Ein einfacher Vergleich zeigt:

set.seed(1) 
v <- sample(1e6) 
system.time(unlist(Map(`:`, v-c, v+c)))    # akrun 1 
#  User  System verstrichen 
#  1.518  0.067  1.595 
system.time(c(sapply(v, function(x) (x-c):(x+c)))) # akrun 2 
#  User  System verstrichen 
#  1.564  0.074  1.652 
system.time(c(t(sapply(-c:c, '+', v))))    # docendo 
#  User  System verstrichen 
#  0.082  0.024  0.106 
system.time(c(mapply(seq, v-c, v+c)))     # 989 
#  User  System verstrichen 
#  7.132  0.123  7.292 
+0

Das ist noch schneller:' unlist (lapply (-c: c, '+ ', v)) ' – digEmAll

+1

@digEmAll, wahr, aber nicht in der Reihenfolge, (sonst würden Sie nicht' t' in meinem Ansatz entweder) –

+0

Oh, ja, du hast Recht – digEmAll

1

Hier ist eine andere sehr schnelle Möglichkeit (vielleicht nicht sehr elegant aber ...):

w <- rep.int(v, rep(c*2+1,length(v))) + (-c:c) 

Benchmark:

library(microbenchmark) 
set.seed(1) 
v <- sample(1e6) 

c <- 3 
microbenchmark(times=30, 
       docendo =c(t(sapply(-c:c, '+', v))), 
       digemall=rep.int(v, rep(c*2+1,length(v))) + (-c:c) 
) 
# Unit: milliseconds 
#  expr  min  lq  mean median  uq  max neval 
# docendo 81.04337 82.50133 100.7718 83.78972 99.89731 169.38202 30 
# digemall 28.57355 30.28533 37.0091 31.01103 32.18491 90.90412 30 

c <- 20 
microbenchmark(times=30, 
       docendo =c(t(sapply(-c:c, '+', v))), 
       digemall=rep.int(v, rep(c*2+1,length(v))) + (-c:c) 
) 
# Unit: milliseconds 
#  expr  min  lq  mean median  uq  max neval 
# docendo 581.9529 626.4765 673.2964 663.0599 713.8367 787.1848 30 
# digemall 174.3748 177.2943 198.9419 180.0702 200.0904 319.6669 30 
Verwandte Themen