R语言编程艺术学习笔记(快速入门、向量)

来源:互联网 发布:python解析json字符串 编辑:程序博客网 时间:2024/05/26 19:18

一、快速入门

1.1.2 批处理模式

pdf("xh.pdf") #set graphical output filehist(rnorm(100)) dev.off() #close the graphical output file
调用pdf()函数告诉R我们想把创建的图形保存在PDF文件xh.pdf中。

调用dev.off()函数关闭正在使用的的图形“设备”,也就是本例中的xh.pdf文件。这就是实际上把文件写入磁盘的机制。

1.3函数入门

oddcount()计算整数向量中奇数的个数

#counts the number of odd integers in xoddcount<-function(x){     k<-0     for(n in x)     {        if (n%%2==1) k<-k+1     }     return(k)}
C/C++程序猿可能把循环写成

for(i in 1:length(x)){   if(x[i]%%2==1) k<-k+1}
R语言编程的戒律之一就是要尽可能避免循环,如果不能避免,就要让循环更简洁。最开始的循环不需要使用length()函数和数组下标。


1.6启动和关闭R

获取工作目录

getwd()
改变工作目录

setwd("D:\\study\\R语言编程艺术")

注意:有时候用"\"会出现由"$s"开头的字符串中存在'\$c',但没有这种逸出号的错误


二、向量

比较重要的是:循环补齐、筛选、向量化。

2.5.1寻找连续出现1的游程

findruns<-function(x,k){    n<-length(x)    runs<-NULL    for (i in 1:(n-k+1)){        if(all(x[i:(i+k-1)]==1)) runs<-c(runs,i)     }      return(runs)}
第五行,我们需要判断x[i]开始的连续k个值是否全部为1。表达式想x[i:i+k-1]语句给出上述子向量的值,然后使用all()函数检验它是否是一个游程。

尽管代码中all()使用比较好,但在建立向量runs的过程并不理想。向量的内存分配比较耗时,由于调用c(runs,i)时给新向量分配了内存空间,每次执行时都会减慢代码运行速度。(这与新向量赋值给runs无关,我们仍然给向量分配了内存空间。)

一种替代方法是预先分配的内存空间,像这样:

findruns1<-function(x,k){   n<-length(x)   runs<-vector(length=n)   count<-0   for(i in 1:(n-k+1)){      if(all(x[i:i+k-1]==1)){         count<-count+1         runs[count]<-i      }    }    if(count>0){        runs<-runs[1:count]     } else runs<-NULL    return(runs)}

在第3行,我们给一个长度为n的向量分配了内存空间。这意味着在执行循环的过程中,可以避免分配新的内存。第8行代码做的只是填充runs。在退出函数之前,我们在第12行重新定义runs,来删除向量中没用的部分。

这种方法更好,第一版代码可能会有很多次内存的分配,而第二版代码降至减少为两次。

2..5.2扩展案例:预测离散值时间序列

1代表有雨,0代表没雨。对于某个固定的K值,我们会根据最近K天的天气记录来预测明天的天气,使用过半数原则:如果在最近K期里1的数量大于k/2,那么预测下一个值为1,否则下一个值为0.对于如何选取K?下面有简单的方法:

preda<-function(x,k){   n<-length(x)   k2<-k/2   pred<-vevtor(length=n-k)   for(i in 1:(n-k)){         if(sum(x[i:(i+(k-1))])>=k2) pred[i]<-1  else pred[i]<-0   return(mean(abs(pred-x[(k+1):n])))}
这段代码的核心是在第7行。此处要预测第i+k天的值(预测结果保存在pred[i]),利用之前的k天的值,也即是第i天,......第i+k-1的值。因此,我们需要算出这些天中的1个个数。由于我们处理的是0-1数据,1的数量可以简单地使用这些天x[j]的总和,它可以很方便的地用以下方法获取:

sum(x[i:(i+k-1)])
使用sum函数和向量索引使得计算更简捷,避免了循环。

下面我们重新写代码,计算过程中利用上一步计算的结果。在循环的每一次迭代中,将更新前一次得到的总和,而不是从头开始计算新的总和。

predb<-function(x,k){     n<-length(x)     k2<-k/2     pred<-vcector(length=n-k)     sm<-sum(x[1:k])     if(sm>=k2) pred[1]<-1 else pred[1]<-0     if(n-k>=2){            for(i in 2:(n-k)){               sm<-sm+x[i+k-1]-x[i-1]               if(sm>=k2) pred[i]<-1 else pred[i]<-0           }     }      return(mean(abs(pred-x[(k+1):n])))}
关键在第9行。在这里从总和sm里减去最早的元素x[i-1],再加上新的元素x[i+k-1],从而更新了sm
2.9.1扩展案例:度量相关性

考虑向量x和y,他们是时间序列,我们定义两者的相关性为x和y同时上升或下降的次说站总观测的比例,即y[i+1]-y[i]与x[i+1]-x[i]符号相同时的次数占总数i的比例。以下是代码:

findud<-function(v){    vud<-v[-1]-v[-length(v)]    return(ifelse(vud.0,1,-1))}udcorr<-functuion(x,y)     ud<lapply(list(x,y,findud))     return(mean(ud[[1]]==ud[[2]]))}



总结:看了两章《R语言编程艺术》,感触很大,以前一直觉得R只是个软件而已,这本书真的是当做一个脚本语言来写,所以说坚持一周看完,收获肯定会很大。



0 0
原创粉丝点击