2014-10-22 5 views
5

Ich bin vertraut mit R, wie ich es seit ein paar Jahren benutze. Leider bin ich nicht sehr versiert darin, Funktionen zu erstellen, die das Wiederholen oder Wiederholen einer Gleichung beinhalten. Das Problem läuft wie folgt ab:Wiederholen oder Schleifen eines Arguments

Ich habe einen Vektor mit mehr als 1000 Werten. Ich möchte den absoluten Unterschied zwischen zwei nebeneinander liegenden Mitteln gleicher Größe aus einer Teilmenge dieses Vektors berechnen.

Hier ist ein Beispiel.

Ich habe den Vektor (VEC) der Länge 8

[1] 0.12472963 1.15341289 -1.09662288 -0.73241639 0.06437658 -0.13647136 -1.52592048 1.46450084 

Ich würde die Mittel der ersten 2 Werte mögen berechnen (0,12472963, 1,15341289) und die absolute Differenz mit dem Mittelwert der folgenden 2-Werte erhalten, (-1.09662288 -0.73241639), danach arbeite ich den Vektor runter.

In diesem Fall kann ich leicht die folgende Gleichung verwenden:

abs(mean(vec[1:2])-mean(vec[3:4])) 

und schrittweise jede Zahl von 1 zu erhöhen, um meinen Weg bis zum Ende des Vektors nach unten manuell zu arbeiten. Ich würde den folgenden Vektor erhalten.

[1] 1.553591 0.3624149 0.8784722 0.497176 0.005337574 

Was ich möchte, aber eine automatisierte Routine haben, dass über lange Vektoren zu tun mir ermöglicht und die Anzahl der Werte, aus denen die Mittel zur Berechnung ändern.

Es scheint mir, dass es relativ einfach sein sollte, aber ich weiß nicht, wo ich anfangen soll.

+1

Sie könnten 'Blick in rollapply()' 'vom zoo' Paket. –

Antwort

7

Verwendung filter.

c(abs(filter(vec, c(0.5, 0.5, -0.5, -0.5), sides=1)[-(1:3)])) 
#[1] 1.55359090 0.36241491 0.87847224 0.49717601 0.00533757 
+0

Scheint, der schnellste bisher eingereichte zu sein. –

2

Mit rollapply von zoo

library(zoo) 
n <- 2 
n1 <- length(vec) 

abs(rollapply(vec[1:(n1-n)], 2, mean)-rollapply(vec[(n+1):n1], 2,mean)) 
#[1] 1.55359090 0.36241491 0.87847224 0.49717601 0.00533757 

Auch andere Variationen des obigen Codes sind (von durch @G kommentiert Grothendieck- einer der Autoren von zoo Paket)

abs(rollmean(vec[1:(n1-n)], 2) - rollmean(vec[(n+1):n1], 2)) #using 
    #`rollmean` instead of `rollapply` 

oder

rollapply(vec, 4, function(x) abs(mean(x[1:2]) - mean(x[3:4]))) 

oder

abs(rollapply(vec, 4, "%*%", c(1, 1, -1, -1)/2)) 
+1

Diese Variationen funktionieren auch: 'abs (rollmean (vec [1: (n1-n)], 2) - rollmean (vec [(n + 1): n1], 2))' und 'rollapply (vec, 4, Funktion (x) abs (Mittelwert (x [1: 2]) - Mittelwert (x [3: 4]))) 'und' abs (Aufrundung (vec, 4, "% *%", c (1, 1, -1, -1)/2)) '. –

+0

@G. Grothendieck Danke für den Kommentar und die Bereitstellung der Variationen. – akrun

1

Wie immer ich im Einklang steht:

vec<-rep(c( 0.12472963 , 1.15341289, -1.09662288, -0.73241639 , 0.06437658, -0.13647136 ,-1.52592048 , 1.46450084 ),100) 

microbenchmark(roland(vec),akrun(vec),times=3) 

Unit: microseconds 
     expr  min   lq  mean median  uq  max 
    roland(vec) 564.128 565.2275 647.3353 566.327 688.939 811.551 
    akrun(vec) 3717.410 3982.1535 4218.3057 4246.897 4468.753 4690.610 
neval 
    3 
    3 
+1

Ich habe meine Antwort mit einer kleinen Änderung aktualisiert, die die Leistung verbessern und die korrekte Handhabung von 'NA'-Werten sicherstellen soll. – Roland

+0

@RichardScriven awwwwww .... :-) –

Verwandte Themen