Đôi khi, chúng ta phải sử dụng các vòng lặp, ví dụ, khi chúng ta không biết có bao nhiêu lần lặp chúng ta cần để có kết quả. Lấy vòng lặp trong khi làm ví dụ. Dưới đây là những phương pháp bạn tuyệt đối nên tránh:
a=numeric(0)
b=1
system.time(
{
while(b<=1e5){
b=b+1
a<-c(a,pi)
}
}
)
# user system elapsed
# 13.2 0.0 13.2
a=numeric(0)
b=1
system.time(
{
while(b<=1e5){
b=b+1
a<-append(a,pi)
}
}
)
# user system elapsed
# 11.06 5.72 16.84
Đây là rất không hiệu quả vì R sao chép vectơ mỗi lần nó xuất hiện.
Cách hiệu quả nhất để chắp thêm là sử dụng chỉ mục. Lưu ý rằng lần này tôi cho phép lặp lại 1e7 lần, nhưng nó vẫn nhanh hơn nhiều c
.
a=numeric(0)
system.time(
{
while(length(a)<1e7){
a[length(a)+1]=pi
}
}
)
# user system elapsed
# 5.71 0.39 6.12
Điều này được chấp nhận. Và chúng ta có thể làm cho nó nhanh hơn một chút bằng cách thay thế [
bằng [[
.
a=numeric(0)
system.time(
{
while(length(a)<1e7){
a[[length(a)+1]]=pi
}
}
)
# user system elapsed
# 5.29 0.38 5.69
Có lẽ bạn đã nhận thấy rằng length
có thể tốn thời gian. Nếu chúng ta thay thế length
bằng một bộ đếm:
a=numeric(0)
b=1
system.time(
{
while(b<=1e7){
a[[b]]=pi
b=b+1
}
}
)
# user system elapsed
# 3.35 0.41 3.76
Như những người dùng khác đã đề cập, việc phân bổ trước vector là rất hữu ích. Nhưng đây là sự đánh đổi giữa tốc độ và mức sử dụng bộ nhớ nếu bạn không biết mình cần bao nhiêu vòng để có kết quả.
a=rep(NaN,2*1e7)
b=1
system.time(
{
while(b<=1e7){
a[[b]]=pi
b=b+1
}
a=a[!is.na(a)]
}
)
# user system elapsed
# 1.57 0.06 1.63
Một phương pháp trung gian là thêm dần các khối kết quả.
a=numeric(0)
b=0
step_count=0
step=1e6
system.time(
{
repeat{
a_step=rep(NaN,step)
for(i in seq_len(step)){
b=b+1
a_step[[i]]=pi
if(b>=1e7){
a_step=a_step[1:i]
break
}
}
a[(step_count*step+1):b]=a_step
if(b>=1e7) break
step_count=step_count+1
}
}
)
#user system elapsed
#1.71 0.17 1.89
vector = values
; hoặc bạn có thể làm vector = vector + giá trị. Nhưng tôi có thể hiểu nhầm trường hợp sử dụng của bạn