2011-01-14 112 views
4

是否可以像下面那樣引導代碼?是否可以矢量化R中矢量元素的順序更新?

length(x) <- 100; 
x[1]  <- 1; 
y   <- rnorm(100); 

for(i in 2:100) { 
    x[i] <- 2 * y[i] * x[i-1]; 
} 

我明白這是一個微不足道的例子,但它可以說明這個想法。

我經常需要編寫代碼,其中向量中的第i個值取決於第(i-1)值,如果可能的話,我想寫這個而不需要for循環,因爲分析建議這種類型的操作的功能是我的代碼中的主要瓶頸。

此操作是否可以向量化,因此我不需要在計算中使用for()循環?

+0

你已經找到R的最薄弱環節:)我恐怕就只有一般的解決方案是將計算降到C級。 – VitoshKa 2011-01-15 11:27:04

回答

10

一般而言,如果您想要矢量化解決方案,您需要解決recurrence relation

+2

感謝您的鏈接+1。我用有限的數學來掙扎,把維基百科的頁面信息轉化爲解決OP問題的東西。如果它不太涉及,你可以擴展你的答案,建議一種直接解決OP的Q的方法嗎? – 2011-01-15 19:57:16

5

在這個例子中,你可以計算出x [i]的公式,看它是否可以被矢量化。在這種情況下,我認爲cumprod可能會起作用。

x <- c(1, cumprod(2*y)[1:99]) 

在某些情況下,如果你還可以在卷積或遞歸模式下使用filter命令。見?filter

但是,如果它是不可能制定出適合模具的一個以上的第n個值的公式,你可以嘗試使用一包像inlineRcpp用C寫這個循環中/ C++。

+0

我沒有得到與使用cumprod解決方案時@kaybenleroll的問題相同的答案。我認爲這也不是什麼問題,`for`循環不會累積超過1,...,n,只是`n-1`的函數。 – 2011-01-15 19:38:13

1

該繪圖命令的內部是等效的。頗爲有趣的反覆運行它:

圖(C(1,2 ^(2:長度(X)-1)* cumprod(RNORM(99))))

0

我沒有全部細節在這個呢,但它看起來功能filter()將是有用的做我所需要的。

0

你可以寫在C++非vertorized代碼:

library(inline) 
myfun <- cxxfunction(signature(y="numeric"), body=' 
Rcpp::NumericVector yvec(y); 
int ysize = yvec.size(); 
Rcpp::NumericVector result(ysize); 
if (ysize > 0) { 
    result[0] = 1; 
    for (int i = 1; i < ysize; i++) { 
     result[i] = 2 * yvec[i] * result[i-1]; 
    } 
} 
return result; 
', plugin="Rcpp") 

然後與R調用這個函數:

y <- rnorm(100); 
x <- myfun(y);