R语言编程艺术学习笔记—第二章

第二章开始就是正式、深入了解R语言的知识点,首先开始了解的是向量相关的知识,牢记三大要点,贯穿始终:

循环补齐、筛选、向量化。

1.添加、删除向量

增加向量主要用插入法,利用向量索引,去达到增加的目的,如下例所示:

> x<-c(1:4)
> x
[1] 1 2 3 4
> x<-(1:2,5,3:4)
> x<-c(x[1:2],5,x[3:4])
> x
[1] 1 2 5 3 4
删除向量主要利用负数的下标,负数后面跟哪个下标就代表删除向量中第几个元素
> x
[1] 1 2 5 3 4
> x[-5]
[1] 1 2 5 3
2.获取向量长度与循环补齐
利用length()函数获取向量长度:
> x<-c(12,14,13,22,67,39,15)
> length(x)
[1] 7
Tips:利用length()函数获取向量中某个值第一次出现的索引值(位置)
代码,定义函数:
first1<-function(x){
 for(i in 1:length(x)){
   if (x[i]==15) break #循环排查,直到第一次出现向量值为15,结束排查
 }
  return(i)
}
运行结果:
> first1<-function(x){
+  for(i in 1:length(x)){
+    if (x[i]==15) break #循环排查,直到第一次出现向量值为15,结束排查
+  }
+   return(i)
+ }
> first1(x)
[1] 7
循环补齐:就是较短的向量会被循环补齐
> x
[1] 12 14 13 22 67 39 15
> y<-c(1:3)
> y
[1] 1 2 3
> x+y
[1] 13 16 16 23 69 42 16
Warning message:
In x + y : longer object length is not a multiple of shorter object length
会有警告提示,但是仍然算出了结果,因为y<-c(1,2,3)为了匹配x中的7个向量,被自动补齐为y<-c(1,2,3,1,2,3,1)与x中对应的1到7个元素相加。
循环补齐对矩阵同样适用,因为矩阵从广义来说也是向量的一种,只是多了行数和列数的属性。
> x<-matrix(1:6,nrow=3)
> x
     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6
> x+1:4
     [,1] [,2]
[1,]    2    8
[2,]    4    6
[3,]    6    8
Warning message:
In x + 1:4 :
  longer object length is not a multiple of shorter object length
上述例子很好说明了这一点,1:4被自动循环补齐为,因为矩阵是按列排序,再次强调
    [,1] [,2]
[1,]    1    4
[2,]    2    1
[3,]    3    2
所以,x中对应6个元素,与上述矩阵6个元素对应相加,得出结果。
3.运算符优先级

运算符优先级从高到低,按照如下顺序排列:注意,冒号优先级高于加减乘除,括号高于冒号

:: :::      access variables in a namespace (作用域限定符)
$ @ component / slot extraction(提取)
[ [[ indexing(括号)
^ exponentiation (right to left)(幂)
- +         unary minus and plus(一元加减)
: sequence operator(顺序运算符)
%any% special operators (including %% and %/%)
* / multiply, divide(乘除)
+ - (binary) add, subtract(加减)
< > <= >= == != ordering and comparison(比较排序)
! negation(非)
& && and(且)
| || or (或)
~ as in formulae(公式中用)
-> ->>  rightwards assignment(右替换左)
<- <<- assignment (right to left)(左替换右)
= assignment (right to left)(相等)

? help (unary and binary)

4.每章案例1—寻找连续出现1的游程
首先,本案例中,游程是指一串连续的数字中,出现连续两个及以上数字的情况,本案例特指出现连续1的游程,并且要求返回索引值。
运行代码:
findruns<-function(x,k){  #函数findruns有两个变量x,k,x指向向量,k指向游程的长度
  n<-length(x) #n指向向量的长度
  runs<-NULL  #runs最初赋值为空
  for(i in 1:(n-k+1)){ 
   if(all(x[i:(i+k-1)]==1)) runs<-c(runs,i)#这里的变量i指定从第一个向量开始,到最后一个组不成游程的值为止(这里的n-k+1就是最后一个组不成游程的值,请好好体会一下)
  }
  return(runs)
}
x<-c(1,0,0,1,1,1,1,1,0,1,1)
findruns(x,3)
输出结果:
> findruns<-function(x,k){ #函数findruns有两个变量x,k,x指向向量,k指向游程的长度
+   n<-length(x) #n指向向量的长度
+   runs<-NULL  #runs最初赋值为空
+   for(i in 1:(n-k+1)){ 
+    if(all(x[i:(i+k-1)]==1)) runs<-c(runs,i)
+   }
+   return(runs)
+ }
> x<-c(1,0,0,1,1,1,1,1,0,1,1)
> findruns(x,3)
[1] 4 5 6

本案例同样经典,理解这个案例就会知道如何编写函数,all()函数要求向量中每一个值都必须为1,以及为什么遍历循环只到最后一个组不成游程的值。

5.每章案例2—预测离散值时间序列
这个案例首先数据集是离散数据,0或者1,1代表有雨,0代表没有雨。x代表全量由0,1组成的数据集,k代表指定的最近天数,如果k=1的次数≥k/2,默认预测值为1,否则为0。
preda<-function(x,k){
 n<-length(x) #n指向向量的长度
  k2<-k/2 #k2指向最近k期一半长度
  pred<-vector(length=n-k) #预测值长度必须比全量向量长度少一个k值,否则就不存在预测了
  for (i in 1:(n-k)){
    if(sum(x[i:(i+(k-1))])>=k2)pred[i]<-1 else pred[i]<-0 #i到i+k-1恰好一个k值长,超过半数,当前预测值指向下雨,从而得到一个由预测值组成的长度为n-k向量
  }
  return(means(abs(pred-x[(k+1):n]))) #用预测值去减实际值,求出平均误差,误差范围[-1,1]之间,越接近0,误差越小

}
6.向量化运算符
1,向量输入,向量输出
 意思很简单,对向量进行操作,输出的结果也是向量

2.向量输入,矩阵输出

主要介绍sapply()函数,一个实例帮助理解:
z12<-function(z) return(c(z,z^2))
sapply(1:8,z12)
输出结果:
> z12<-function(z) return(c(z,z^2))
> sapply(1:8,z12)
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,]    1    2    3    4    5    6    7    8
[2,]    1    4    9   16   25   36   49   64
> 
这里sapply()函数的作用是对1:8的每个元素,使用函数function(),返回结果是元素的平方
sapply(a,b),对对象a,调用函数b,返回结果由函数b决定
注:这里返回结果是矩阵,并且返回结果是 按行排序的!另一个lapply()函数,功能相似,但lapply()函数只针对列表

3.NA(缺失值)与NULL(空值)

(1)调用函数时,跳过缺失值的方法

例:mean(x,na.rm =T)  利用na.rm =T就可以剔除缺失值(na.rm 意思 na.remove)

(2)空值的用法

最典型的用法是在循环中创建向量,上面的每章案例1用的就是这个方法,不了解的请回看。NULL也不会被计数。

7.筛选
(1)使用subset()函数进行筛选
subset()进行筛选时会自动剔除缺失值NA
> x<-c(6,1:3,NA,12)
> subset(x,x>5) #第一个是向量,第二个是筛选条件
[1]  6 12
(2)使用which()函数返回索引的位置
     一个经典的例子阐述which()函数的用法,返回数据集中第一个1出现的位置
first1<-function(x){
  for(i in 1:length(x)){
   if(x[i]==1) break
  }
  return(i)
}
x<-c(2:5,1,3:6)
first1(x)
输出结果:
> first1<-function(x){
+   for(i in 1:length(x)){
+    if(x[i]==1) break
+   }
+   return(i)
+ }
> x<-c(2:5,1,3:6)
> first1(x)
[1] 5
8.熟悉ifelse()函数
ifelse(b,u,v)
b指对操作对象运用某个函数,符合条件的返回u,不符合条件的返回v

9.每章案例3—度量相关性

这里案例如果有统计学背景,会帮助理解,当然,没有统计学背景也很好理解。这个案例将前面几个函数的运用串联起来
案例简述:有两个时间序列x和y,代表每小时收集的气温和气压的测量值,定义x和y的相关性为他们同时上升和下降次数占总观测数的比例,看清题目很重要,这是你编程思路的基础(实际的工作中根本没有题目,只有业务问题,要把业务问题梳理成可以解决的题目是我们要做的),首先是要算出x和y上升和下降的次数,另外要算出它们同时上升和下降的次数,最后算出这些同步次数占总观测数的比例,先上代码:

findud<-function(v)
{vud<-v[-1]-v[-length(v)] #这行代码巧妙实现了后一个值减前一个值,利用-号
return(ifelse(vud>0,1,-1)) #上升趋势返回1,下降趋势返回-1
}
udcorr<-function(x,y){
  ud<-lapply(list(x,y),findud)#利用lapply()函数求出由x和y的上升、下降行成的向量
  return(mean(ud[[1]]==ud[[2]]))#默认将列表均分为两列,找出第一列和第二列趋势相同的值,相同默认返回true(即1),最后求出均值
}
x<-c(5,12,13,3,6,0,1,15,16,8,88)
y<-c(4,2,3,23,6,10,11,12,6,3,2)
udcorr(x,y)

输出结果:

 findud<-function(v){
+   vud<-v[-1]-v[-length(v)]  #这行代码巧妙实现了后一个值减前一个值,利用-号
+   return(ifelse(vud>0,1,-1)) #上升趋势返回1,下降趋势返回-1
+ }
> udcorr<-function(x,y){
+   ud<-lapply(list(x,y),findud)#利用lapply()函数求出由x和y的上升、下降行成的向量
+   return(mean(ud[[1]]==ud[[2]]))#默认将列表均分为两列,找出第一列和第二列趋势相同的值,相同默认返回true(即1),最后求出均值
+ }
> x<-c(5,12,13,3,6,0,1,15,16,8,88)
> y<-c(4,2,3,23,6,10,11,12,6,3,2)
> udcorr(x,y)
[1] 0.4

本例中,x和y在10次中同时上升3次,得到相关性应为4/10=0.4,代码输出结果一致。当编程技巧提高时,上述代码可以简化

findud<-function(v){

  vud<-v[-1]-v[-length(v)]  #这行代码巧妙实现了后一个值减前一个值,利用-号
  return(ifelse(vud>0,1,-1)) #上升趋势返回1,下降趋势返回-1
}
udcorr<-function(x,y) mean(sign(diff(x))==sign(diff(y))) #diff()函数代表滞后,即后面的值减前面的值,滞后1期就是后一个减前一个,滞后2期是第3个减第1个,第4个减第2个

如果这些案例完全理解,相信会对向量有比较深刻的印象!

第二章向量学习笔记到此结束,下章矩阵和数组再见!












你可能感兴趣的:(R语言编程艺术学习笔记—第二章)