2015-10-15 60 views
0

的我試圖一個載體複製到另一個使用的語法如下:有效利用向量

data<-NULL 
for(i in 1:nrow(line)){ 
    data=append(data,line[i*4]) 
} 

從我所看到的,在大量的數據複製使用這種方式的結果append,這使得R非常緩慢。考慮到您從中複製的列表具有給定的大小,將一個數組的第四個元素複製到另一個數組的第四個元素的語法是什麼?

+0

最好的方法是預先分配一個「out」向量並複製那裏的所有內容。 –

+3

目前還不清楚你在問什麼。難道你不能創建一個索引向量,說'j'並將其用於子集你的向量'線'?然後執行'data < - line [j]'。 – 2015-10-15 05:27:42

+1

做一個可重現的例子,包括你想要的輸出。 – Frank

回答

2

這裏有三個方法與他們的基準。你可以看到,在method2函數中預分配矢量的速度比較快,而lapply方法是中等的,而你的函數是最慢的。

當然,這些是一維向量,而不是n-D陣列,但我預計基準會相似或更明顯。

method1 <- function(line) { 
    data<-NULL 
    for(i in 1:length(line)){ 
    data=append(data,line[i]) 
    } 
} 

method2 <- function(line) { 
    data <- vector(mode="numeric", length = length(line)) 
    for (i in 1:length(line)) { 
    data[i] <- line[i] 
    } 
} 

library(microbenchmark) 
r <- rnorm(1000) 
microbenchmark(method2(r), unit="ms") 
#> Unit: milliseconds 
#>  expr  min  lq  mean median  uq  max neval 
#> method2(r) 2.18085 2.279676 2.428731 2.371593 2.500495 5.24888 100 
microbenchmark(lapply(r, function(x) { data<-append(data, x) }), unit="ms") 
#> Unit: milliseconds 
#>             expr  min  lq 
#> lapply(r, function(x) {  data <- append(data, x) }) 3.014673 3.091299 
#>  mean median  uq  max neval 
#> 3.287216 3.150052 3.260199 6.036501 100 
microbenchmark(method1(r), unit="ms") 
#> Unit: milliseconds 
#>  expr  min  lq mean median  uq  max neval 
#> method1(r) 3.938684 3.978002 5.71831 4.020001 4.280521 98.58584 100 

沒有意識到OP只想每四分之一。爲什麼不使用數據框或data.table?

d <- data.frame(matrix(rnorm(1000), ncol=1)) 
microbenchmark(d2 <- d[seq(1,nrow(d), 4),]) 
#> Unit: microseconds 
#>       expr min  lq  mean median  uq 
#> d2 <- d[seq(1, nrow(d), 4), ] 64.846 65.9915 73.08007 67.225 73.8225 
#>  max neval 
#> 220.438 100 
library(data.table) 
dt <- data.table(d) 
microbenchmark(d2 <- dt[seq(1,nrow(d), 4),]) 
#> Unit: microseconds 
#>       expr  min  lq  mean median  uq 
#> d2 <- dt[seq(1, nrow(d), 4), ] 298.163 315.2025 324.8793 320.554 330.416 
#>  max neval 
#> 655.124 100 
+0

這三種方法似乎都是將所有行簡單地複製到數據中,而不是按照OP的要求複製每四個元素。 – josliber

+0

沒有意識到,編輯和感謝。 – potterzot

+0

謝謝你解釋得非常好 – Dave

2

如果你想每四個元素從​​向量提取,你可以使用索引來seq搶正確的元素:如您在您的問題顯示

data <- letters[seq(4, length(letters), by=4)] 
data 
# [1] "d" "h" "l" "p" "t" "x" 

在我成長的一個載體將速度較慢,因爲您需要繼續重新分配矢量(有關詳細信息,請參閱The R Inferno的第二個圓圈)。然而,與在單個矢量化索引操作中構建矢量相比,即使預先分配矢量並使用for循環構建該矢量也會很慢。

要獲得的速度提高意識,考慮一個比較排序你所描述的方法,但是使用了預分配:

for.prealloc <- function(x) { 
    data <- vector(mode="numeric", length = floor(length(x)/4)) 
    for (i in 1:floor(length(x)/4)) { 
    data[i] <- x[i*4] 
    } 
    data 
} 
josilber <- function(x) x[seq(4, length(x), by=4)] 
r <- rnorm(10000) 
all.equal(for.prealloc(r), josilber(r)) 
# [1] TRUE 

library(microbenchmark) 
microbenchmark(for.prealloc(r), josilber(r)) 
# Unit: microseconds 
#    expr  min  lq  mean median  uq  max neval 
# for.prealloc(r) 1846.014 2035.7890 2351.9681 2094.804 2244.56 5283.285 100 
#  josilber(r) 95.757 97.4125 125.9877 113.179 138.96 259.606 100 

我建議這種方法比使用for快20倍,一個預先分配的向量(它將比使用append和一個非預先分配的向量更快)。