2014-10-22 8 views
5

Я знаком с R, поскольку я использовал его уже несколько лет. К сожалению, я не очень хорошо разбираюсь в создании функций, которые включают цикл или повторение уравнения. Проблема заключается в следующем:Повторение или зацикливание аргумента

У меня есть вектор, содержащий более 1000 значений. Я хотел бы рассчитать абсолютную разницу между двумя сопоставимыми средствами равного размера из подмножества этого вектора.

Вот пример.

У меня есть вектор (VEC) длиной 8

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

Я хотел бы вычислить среднее из первых 2-х значений (0.12472963, 1.15341289) и получить абсолютную разность со средним из 2 следующих значений (-1.09662288 -0,73241639), после этого, работая по пути вниз по вектору.

В этом случае, я могу легко использовать следующее уравнение:

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

и постепенно увеличивать каждое число на 1 таким образом, чтобы работать свой путь вниз вручную до конца вектора. Я бы получил следующий вектор.

[1] 1.553591 0.3624149 0.8784722 0.497176 0.005337574 

То, что я хотел бы, однако, иметь автоматизированную процедуру, которая позволяет быть мне сделать это более длинные векторы и изменить количество значений, из которых можно рассчитать средства.

Мне кажется, что это должно быть относительно просто, но я не знаю с чего начать.

+1

Вы можете посмотреть в 'rollapply()' 'от zoo' пакета. –

ответ

7

Использование 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

Появляется как самый быстрый из представленных до сих пор. –

2

Использования rollapply из 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 

Кроме того, другие вариантов вышеприведенного кода (от прокомментировано @G Grothendieck- один из авторов zoo пакета)

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

или

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

или

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

Эти вариации также работают: 'abs (rollmean (vec [1: (n1-n)], 2) - rollmean (vec [(n + 1): n1], 2))' и 'rollapply (vec, 4, функция (x) abs (средняя (x [1: 2]) - средняя (x [3: 4]))) 'и' abs (rollapply (vec, 4, "% *%", c (1, 1, -1, -1)/2)). –

+0

@G. Grothendieck Спасибо за комментарий и предоставим варианты. – akrun

1

Как всегда, я куранты в с:

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

Я обновил свой ответ с небольшими изменениями, которые должны улучшить производительность и обеспечить правильную обработку значений «NA». – Roland

+0

@RichardScriven awwwwww .... :-) –