2015-03-23 5 views
5

Я думаю, у меня есть довольно простой вопрос для R, но у меня проблемы с поиском примера. Скажем, у меня есть вектор чиселR: Выполнение вычисления на векторе

practice<-c(1,2,10,15,17,1,2,4) 

и я хочу рассчитать изменение между числами. Длина вектора фиксируется при 36 наблюдениях. Пример того, что я хочу вычислить, это ((2/1) -1), ((10/2-1), .... Я думаю о построении цикла for, где я ссылаюсь на позицию и имею счетчик, связанный с он.

+3

Выньте проклятые петли из головы. Мы не используем их в 99% случаев в R. Просто занимайтесь практикой [-1L]/practice [-length (practice)] - 1L' –

+0

В одном вопросе вы можете определить, что такое -1L. Вы бы определили L выше этого как длину вектора или у него есть определенное значение в R? – user3549613

+0

'1L' является одним длинным, то есть 1 как длинное целое число. –

ответ

5

Одним из преимуществ использования R является его vectorization, что означает, что он может легко выполнять операции на весь вектор сразу же вместо того, чтобы цикл по каждому элементу.

Как Дэвид Arenburg упоминается в комментарий (с обновлениями благодаря BondedDust и Домиником COMTOIS), вы можете в вашем случае это сделать:

practice[-1]/head(practice, -1) - 1 

Что это сделать

?

practice[-1] ссылки на весь вектор, кроме первого элемента.

> practice[-1] 
[1] 2 10 15 17 1 2 4 

Аналогично, head(practice, -1) ссылается на весь вектор, за исключением последнего элемента.

> head(practice, -1) 
[1] 1 2 10 15 17 1 2 

Если мы разделим эти, мы получаем вектор, состоящий из каждого элемента исходного вектора, деленная на элемент, который предшествует ему. Мы можем разделить эти векторы непосредственно, потому что деление является векторизованной операцией.

> practice[-1]/head(practice, -1) 
[1] 2.0000 5.0000 1.5000 1.1333 0.0588 2.0000 2.0000 
> # ^ ^ ^ ^ ^ ^ ^
> # 2/1 10/2 15/10 17/15 1/17 2/1 4/2 

Как у вас есть в вашем примере, мы можем вычесть 1 в конце.

> practice[-1]/head(practice, -1) - 1 
[1] 1.0000 4.0000 0.5000 0.1333 -0.9412 1.0000 1.0000 

Это применяется к каждому элементу вектора, поскольку добавление также Векторизованная операция в R.

Нет петли необходимы!

код эквивалентный цикл будет таким:

x <- NULL 
for (i in 1:(length(practice) - 1)) { 
    x[i] <- practice[i + 1]/practice[i] - 1 
} 
x 
[1] 1.0000 4.0000 0.5000 0.1333 -0.9412 1.0000 1.0000 

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

+2

'tail (practice, -1)' более компактный и выразительный, чем 'practice [-length (practice)]' –

+0

@BondedDust: Спасибо за отзыв, я ценю его. Обновлен мой ответ. –

+2

Фактически 'tail (practice, -1)' ** равно ** 'practice [-1]'. Я думаю, что вы имели в виду 'head (practice, -1)' –

Смежные вопросы