บางครั้งเราต้องใช้ลูปตัวอย่างเช่นเมื่อเราไม่รู้จำนวนการวนซ้ำที่เราต้องการเพื่อให้ได้ผลลัพธ์ ใช้ในขณะที่ลูปเป็นตัวอย่าง ด้านล่างเป็นวิธีที่คุณควรหลีกเลี่ยงอย่างยิ่ง:
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
สิ่งเหล่านี้ไม่มีประสิทธิภาพมากเพราะ R คัดลอกเวกเตอร์ทุกครั้งที่ผนวกเข้าด้วยกัน
วิธีที่มีประสิทธิภาพที่สุดในการผนวกคือการใช้ดัชนี โปรดทราบว่าในครั้งนี้ฉันปล่อยให้มันวนซ้ำ 1e7 ครั้ง แต่ก็ยังเร็วกว่าc
มาก
a=numeric(0)
system.time(
{
while(length(a)<1e7){
a[length(a)+1]=pi
}
}
)
# user system elapsed
# 5.71 0.39 6.12
นี่เป็นที่ยอมรับ และเราสามารถทำให้มันบิตเร็วขึ้นโดยการแทนที่ด้วย[
[[
a=numeric(0)
system.time(
{
while(length(a)<1e7){
a[[length(a)+1]]=pi
}
}
)
# user system elapsed
# 5.29 0.38 5.69
บางทีคุณอาจสังเกตว่าlength
อาจใช้เวลานาน หากเราแทนที่length
ด้วยตัวนับ:
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
ดังที่ผู้ใช้รายอื่นกล่าวถึงการจัดสรรเวกเตอร์ล่วงหน้านั้นมีประโยชน์มาก แต่นี่เป็นการแลกเปลี่ยนระหว่างความเร็วและการใช้หน่วยความจำหากคุณไม่ทราบว่าคุณต้องได้รับลูปกี่ครั้ง
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
วิธีการขั้นกลางคือการค่อยๆเพิ่มบล็อกของผลลัพธ์
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
; หรือคุณสามารถทำค่า vector = vector + แต่ฉันอาจจะเข้าใจผิดกรณีที่คุณใช้งาน