您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 咨询培训 > R语言入门_十三章、十四章
第十三章调试案例:寻找连续为1的游程findruns1-function(x,k){n-length(x)runs-vector(length=n)count-0for(iin1:(n-k+1)){if(all(x[i:i+k-1]==1)){count-count+1runs[count]-i}}if(count0){runs-runs[1:count]}elseruns-NULLreturn(runs)}findruns1(c(1,0,0,1,1,0,0,1,1,1),2)[1]34789显然,出错了调试方法一:手动,在程序中添加多个print(),把程序的内部细节输出来查看是哪里出的问题。function(x,k){print(x)#输出xprint(k)#输出kn-length(x)print(n)#输出nruns-vector(length=n)count-0for(iin1:(n-k+1)){if(all(x[i:i+k-1]==1)){count-count+1runs[count]-iprint(runs)#输出循环的每一步}}if(count0){runs-runs[1:count]print(runs)#输出结果}elseruns-NULLreturn(runs)}findruns1(c(1,0,0,1,1,0,0,1,1,1),2)[1]1001100111#正确[1]2#正确[1]10#正确[1]3000000000#出错!![1]3400000000[1]3470000000[1]3478000000[1]3478900000[1]34789[1]34789可以看出,从把实参带入形参,到建立长度等于x长度d的向量,都是正确的。错误开始于循环的第一步。因此我们应该去检查循环语句,不难发现,问题出在all(x[i:i+k-1]==1)中,我们没有把i+k-1扩起来。调试方法二:使用R的调试工具在代码中插入print()显然比较繁琐,特别是程序较长的时候,使用R的调试工具会更便捷。R的核心调试工具有浏览器构成,它可以让你逐行运行代码,并在运行过程中检查,可以用dubug(f)或browser()打开这个浏览器。debug(f)函数可以把函数f()设置成调试状态,意味着每次调用f()都会进入这一状态,取消这一状态需调用undebug(f)。在2.10版本之后,可以用debugonce()代替(检查漏洞一次)。debugonce(findruns1)findruns1(c(1,0,0,1,1,0,0,1,1,1),2)然后开始调试….Browse[2]x[1]1001100111Browse[2]debugatfindruns1.R#2:n-length(x)Browse[2]debugatfindruns1.R#3:runs-vector(length=n)Browse[2]print(n)[1]10Browse[2]debugatfindruns1.R#4:count-0Browse[2]debugatfindruns1.R#5:for(iin1:(n-k+1)){if(all(x[i:i+k-1]==1)){count-count+1runs[count]-i}}Browse[2]debugatfindruns1.R#5:iBrowse[2]debugatfindruns1.R#6:if(all(x[i:i+k-1]==1)){count-count+1runs[count]-i}Browse[2]x[i:i+k-1]#出错[1]0Browse[2]i:i+k-1[1]2Browse[2]i[1]1Browse[2]k[1]2Browse[2]Q#退出调试思考后可以发现,少加了括号。source(findruns.R)findruns(c(1,0,0,1,1,0,0,1,1,1),2)[1]489正确。下面这个案例是用递归算法排序qs-function(x){if(length(x)=1)return(x)pivot-x[1]therest-x[-1]sv1-therest[therestpivot]sv2-therest[therest=pivot]sv1-qs(sv1)sv2-qs(sv2)return(c(sv1,pivot,sv2))}a-c(8,7,2,9,45,32)source(qs.R)a-c(8,7,2,9,45,32)qs(a)[1]27893245结果是正确的,但运算过程是比较让人费解的。本人要说明的是,调试工具不仅可以找错,也可以帮助理解程序的运行过程。debugonce(qs)qs(a)debuggingin:qs(a)debugatqs.R#1:{if(length(x)=1)return(x)pivot-x[1]therest-x[-1]sv1-therest[therestpivot]sv2-therest[therest=pivot]sv1-qs(sv1)sv2-qs(sv2)return(c(sv1,pivot,sv2))}Browse[2]debugatqs.R#2:if(length(x)=1)return(x)Browse[2]debugatqs.R#2:NULLBrowse[2]x[1]87294532Browse[2]length(x)[1]6Browse[2]debugatqs.R#3:pivot-x[1]Browse[2]pivotError:object'pivot'notfoundBrowse[2]debugatqs.R#4:therest-x[-1]Browse[2]pivot[1]8Browse[2]debugatqs.R#5:sv1-therest[therestpivot]Browse[2]therest[1]7294532Browse[2]debugatqs.R#6:sv2-therest[therest=pivot]Browse[2]sv1[1]72Browse[2]debugatqs.R#7:sv1-qs(sv1)Browse[2]sv2[1]94532Browse[2]debugatqs.R#8:sv2-qs(sv2)Browse[2]sv1[1]27Browse[2]debugatqs.R#9:return(c(sv1,pivot,sv2))Browse[2]sv2[1]93245Browse[2][1]27893245看到每一步的结果,对程序的理解必然会更深刻。第十四章性能提升:速度和内存本章主要介绍通过向量化(相对for()循环,可以理解向量化的意思是处理长向量而不是把向量截成单个分别处理)的方式优化自己的R代码。当然,提升速度最好的方法永远是直接用C或C++编写代码。x-runif(10000000)y-runif(10000000)z-vector(length=10000000)system.time(z-x+y)usersystemelapsed0.080.060.14system.time(for(iin1:length(x))z[i]-x[i]+y[i])usersystemelapsed36.830.0636.89三个数字分别表示“用户”是消耗在应用程序(非操作系统部分)执行的时间,“系统”是底层操作系统执行(例如磁盘读写等)部分的时间,“流逝”是经过的总时间(可以认为是前两者的总和)。一般优化时主要关注“用户”的时间。可以看出,向量化的运行速度远远高于for()循环下面是第八章出现的例子sum-0nreps-100000for(iin1:nreps){xy-rnorm(2)sum-sum+max(xy)}print(sum/nreps)emax-function(nreps){x-rnorm(2*nreps)maxxy-pmax(x[1:nreps],x[(nreps+1):(2*nreps)])return(mean(maxxy))}emax(100000)system.time(source(MaxNorm.R))[1]0.5628218usersystemelapsed0.720.000.74system.time(source(MaxNorm2.R))[1]0.5678636usersystemelapsed0.030.000.03当然,速度的提升是以更多内存消耗为代价的,因为我们将所有的数据进行存储在计算,而不是每次生成一对取较大值后就丢失较小值。所以,时间和空间的权衡经常无法避免。函数式拷贝和内存问题当R中已经创建的向量或向量的一个对象发生变化时,程序会在另一块内存区域创建一份整个对象拷贝,所以只有第一次改变赋值时会有消耗。但如果是列表或数据框就会每次都创建。z-1:10000000system.time(z[3]-8)usersystemelapsed0.060.000.06system.time(z[33]-88)usersystemelapsed000m-5000n-1000z-list()for(iin1:m)z[[i]]-sample(1:10,n,replace=T)system.time(for(iin1:m)z[[i]][3]-8)usersystemelapsed0.060.000.06z-matrix(sample(1:10,m*n,replace=T),nrow=m)system.time(z[,3]-8)usersystemelapsed0.030.000.03
本文标题:R语言入门_十三章、十四章
链接地址:https://www.777doc.com/doc-3552950 .html