2015-03-14 15 views
7

Tôi muốn tăng tốc độ vòng lặp của tôi thông qua vectơ hóa hoặc sử dụng Data.table hoặc một thứ khác. Tôi phải chạy mã trên 1.000.000 hàng và mã của tôi thực sự chậm.Làm thế nào để tăng tốc độ hoặc vectơ một vòng lặp for?

Mã này khá tự giải thích. Tôi đã bao gồm một lời giải thích dưới đây chỉ trong trường hợp. Tôi đã bao gồm đầu vào và đầu ra của hàm. Hy vọng rằng bạn sẽ giúp tôi thực hiện chức năng nhanh hơn.

MyMục tiêu là để ngăn chặn vectơ "Âm lượng", trong đó mỗi thùng bằng 100 lượt chia sẻ. Vector "Volume" chứa số lượng cổ phiếu được giao dịch. Đây là hình thức của nó:

head(Volume, n = 60) 
[1] 5 3 1 5 3 1 1 1 1 1 1 1 18 1 1 18 2 7 13 2 7 13 3 2 1 1 3 2 1 1 1 
[32] 1 6 6 1 1 1 1 1 1 1 1 18 2 1 1 2 1 14 18 2 1 1 2 1 14 1 1 9 5 

Vectơ "binIdexVector" có cùng độ dài "Tập" và chứa số bin; đó là mỗi phần tử của 100 cổ phiếu đầu tiên nhận được số 1, mỗi phần tử của 100 cổ phiếu tiếp theo nhận được số 2, mỗi phần tử của 100 cổ phiếu tiếp theo nhận được số 3, v.v. Đây là những gì vector trông giống như:

head(binIdexVector, n = 60) 
[1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 
[48] 2 2 3 3 3 3 3 3 3 3 3 3 3 

Đây là chức năng của tôi:

#input as a vector 
Volume<-c(5L, 3L, 1L, 5L, 3L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 18L, 1L, 1L, 
        18L, 2L, 7L, 13L, 2L, 7L, 13L, 3L, 2L, 1L, 1L, 3L, 2L, 1L, 1L, 
        1L, 1L, 6L, 6L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 18L, 2L, 1L, 
        1L, 2L, 1L, 14L, 18L, 2L, 1L, 1L, 2L, 1L, 14L, 1L, 1L, 9L, 5L, 
        2L, 1L, 1L, 1L, 1L, 9L, 5L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 3L, 1L, 
        1L, 2L, 1L, 2L, 1L, 1L, 3L, 1L, 1L, 2L, 9L, 9L, 3L, 3L, 1L, 1L, 
        1L, 1L, 5L, 5L, 8L, 8L, 2L, 1L, 2L, 1L, 10L, 10L, 10L, 10L, 10L, 
        10L, 10L, 10L, 9L, 9L, 1L, 1L, 8L, 1L, 8L, 1L, 8L, 8L, 2L, 1L, 
        1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 
        1L, 1L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 5L, 5L, 
        1L, 2L, 7L, 1L, 2L, 7L, 1L, 1L, 1L, 1L, 2L, 1L, 10L, 1L, 1L, 
        1L, 1L, 1L, 1L, 2L, 1L, 10L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
        1L, 1L, 30L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 3L, 
        1L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 2L, 2L, 2L, 1L, 2L, 1L, 
        10L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 10L, 1L, 1L, 1L, 1L, 1L, 
        1L, 1L, 1L, 1L, 1L, 30L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
        1L, 1L, 3L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 2L, 2L, 2L, 
        1L, 1L, 1L, 1L, 1L, 1L, 1L, 7L, 7L, 3L, 1L, 1L, 1L, 4L, 3L, 1L, 
        1L, 1L, 4L, 25L, 1L, 1L, 25L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 
        1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L) 

binIdexVector <- numeric(length(Volume)) 

# initialize 
binIdex <-1 
totalVolume <-0 

for(i in seq_len(length(Volume))){ 

    totalVolume <- totalVolume + Volume[i] 

    if (totalVolume <= 100) { 

    binIdexVector[i] <- binIdex 

    } else { 

    binIdex <- binIdex + 1 
    binIdexVector[i] <- binIdex 
    totalVolume <- Volume[i] 
    } 
} 

# output: 
> dput(binIdexVector) 
c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
    1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
    2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
    3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
    4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 
    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 
    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 
    7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 
    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 
    8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 
    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10) 

Cảm ơn rất nhiều sự giúp đỡ của bạn!

> sessionInfo() 
R version 3.1.2 (2014-10-31) 
Platform: x86_64-w64-mingw32/x64 (64-bit) 

locale: 
[1] LC_COLLATE=English_United States.1252 LC_CTYPE=English_United States.1252 
[3] LC_MONETARY=English_United States.1252 LC_NUMERIC=C       
[5] LC_TIME=English_United States.1252  

attached base packages: 
[1] stats  graphics grDevices utils  datasets methods base  

loaded via a namespace (and not attached): 
[1] tools_3.1.2 

Trả lời

11

Bạn có thể sử dụng Rcpp khi vector hóa khó.

library(Rcpp) 
cppFunction(' 
    IntegerVector bin(NumericVector Volume, int n) { 
    IntegerVector binIdexVector(Volume.size()); 
    int binIdex = 1; 
    double totalVolume =0; 

    for(int i=0; i<Volume.size(); i++){ 
     totalVolume = totalVolume + Volume[i]; 
     if (totalVolume <= n) { 
     binIdexVector[i] = binIdex; 
     } else { 
     binIdex++; 
     binIdexVector[i] = binIdex; 
     totalVolume = Volume[i]; 
     } 
    } 
    return binIdexVector; 
    }') 

all.equal(bin(Volume, 100), binIdexVector) 
#[1] TRUE 

Đó là nhanh hơn so với findInterval(cumsum(Volume), seq(0, sum(Volume), by=100)) (trong đó tất nhiên đưa ra một câu trả lời không chính xác)

+0

cảm ơn bạn rất nhiều.Tôi chạy nó trên 5 triệu hàng. Chức năng của tôi mất 10,62 giây và của bạn mất một whopping 0,063 giây Cảm ơn một lần nữa – user3602239

+0

Thực ra đây là chức năng của bạn. – Khashaa

0
Volume<-sample(1:5,500,replace=TRUE) 
binLabels<- cumsum(diff(cumsum(Volume) %% 100) <0) + 1 

Điều này dẫn đến các vector binLabels mà chỉ mà bin mỗi điểm dữ liệu thuộc về. Mỗi thùng sẽ chứa số điểm dữ liệu cần thiết sao cho tổng số điểm dữ liệu là 100.

+0

Hi Keegan, cảm ơn bạn đã giúp đỡ của bạn. Khi tôi chạy binLabels trên khối lượng vector trong mã của tôi, tôi không nhận được cùng một đầu ra như trong binIdexVector. Sử dụng chức năng của bạn, các nhãn bắt đầu từ 0 và kết thúc ở 4, trong khi đầu ra của tôi bắt đầu ở 1 và kết thúc ở 10. Bạn có thể chạy hàm của vectơ khối lượng trong mã của tôi và thấy sự khác biệt không? Một lần nữa cảm ơn bạn đã giúp đỡ của bạn – user3602239

+0

đúng, tôi đã thực hiện một thay đổi của tôi. Câu hỏi nhanh về bạn - bạn không muốn 'totalVolume' đặt lại thành 0 mỗi lần vượt quá 100? Vì vậy, 'totalVolume <-0' nên ở bên trong vòng lặp? Hay tôi hiểu nhầm mục đích? – keegan

+0

khi nó vượt quá 100, hàm sẽ đi vào phần "khác". Tôi muốn totalVolume được bằng với hàng tiếp theo và bắt đầu thêm từ đó. Nếu totalVolume <-0 nằm trong vòng lặp, hàng vượt quá 100 sẽ không được thêm vào và vòng lặp sẽ xuất hiện trên hàng tiếp theo. – user3602239

Các vấn đề liên quan