R语言笔记之语法篇

Posted tonydandelion2014

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了R语言笔记之语法篇相关的知识,希望对你有一定的参考价值。

R语言基础之语法

分支结构If…else…和 Ifelse()函数

Ifelse()函数是支持向量化计算的,ifelse(判断条件,为真的时候返回的变量,条件为假的时候返回的变量)。

举例

> (Brand=paste(c(‘Brand‘),1:9,sep=‘‘))
[1] "Brand1" "Brand2" "Brand3" "Brand4" "Brand5" "Brand6" "Brand7" "Brand8" "Brand9"
> (PName=paste(c(‘Dell‘),1:9,sep=‘‘))
[1] "Dell1" "Dell2" "Dell3" "Dell4" "Dell5" "Dell6" "Dell7" "Dell8" "Dell9"
> (Men=rep(c(‘1G‘,‘2G‘,‘4G‘),times=3))
[1] "1G" "2G" "4G" "1G" "2G" "4G" "1G" "2G" "4G"
> (Feq=rep(c(‘2.2G‘,‘2.8G‘,‘3.3G‘),each=3))
[1] "2.2G" "2.2G" "2.2G" "2.8G" "2.8G" "2.8G" "3.3G" "3.3G" "3.3G"
> (Price=rep(c(1000,2000,5000),3))
[1] 1000 2000 5000 1000 2000 5000 1000 2000 5000
> PC=data.frame(Brand,PName,Men,Feq,Price)
> #初始化,先为每个电脑都先打上Cheap标签
> PC$PD = rep(‘Cheap‘,9)
> for (i in 1:nrow(PC)){  #遍历PC数据框
+   if(PC[i,‘Price‘]>3000){ 
+     #当价格大于3000的时候,就改成Expensive
+     PC[i,‘PD‘]=‘Expensive‘
+   }
+ }
> PC #从输出结果来看,每个品牌的电脑,都被标定了价格。
   Brand PName Men  Feq Price        PD
1 Brand1 Dell1  1G 2.2G  1000     Cheap
2 Brand2 Dell2  2G 2.2G  2000     Cheap
3 Brand3 Dell3  4G 2.2G  5000 Expensive
4 Brand4 Dell4  1G 2.8G  1000     Cheap
5 Brand5 Dell5  2G 2.8G  2000     Cheap
6 Brand6 Dell6  4G 2.8G  5000 Expensive
7 Brand7 Dell7  1G 3.3G  1000     Cheap
8 Brand8 Dell8  2G 3.3G  2000     Cheap
9 Brand9 Dell9  4G 3.3G  5000 Expensive

> PC$PD2=ifelse(PC$Price>3000,‘Expensive‘,‘Cheap‘) #用ifelse函数来实现相同的功能更方便
> PC
   Brand PName Men  Feq Price        PD       PD2
1 Brand1 Dell1  1G 2.2G  1000     Cheap     Cheap
2 Brand2 Dell2  2G 2.2G  2000     Cheap     Cheap
3 Brand3 Dell3  4G 2.2G  5000 Expensive Expensive
4 Brand4 Dell4  1G 2.8G  1000     Cheap     Cheap
5 Brand5 Dell5  2G 2.8G  2000     Cheap     Cheap
6 Brand6 Dell6  4G 2.8G  5000 Expensive Expensive
7 Brand7 Dell7  1G 3.3G  1000     Cheap     Cheap
8 Brand8 Dell8  2G 3.3G  2000     Cheap     Cheap
9 Brand9 Dell9  4G 3.3G  5000 Expensive Expensive

> PC$Price #PC$Prince是一个向量ifelse能完成向量化计算,对每一个元素作比较返回相应的值。
[1] 1000 2000 5000 1000 2000 5000 1000 2000 5000

循环结构

for循环

从向量x中取出单个数据存到临时变量n当中,每取出一次,就执行一次循环体。
for(n in x){

}

举例

> for(x in 1:5){
+   print (x^2)
+ }
[1] 1
[1] 4
[1] 9
[1] 16
[1] 25

while循环

condition为真的时候执行循环体
while(condition){
….
}

举例

> i = 1
> while(i<6){
+   print (x^2)
+   i = i + 1
+ }
[1] 25
[1] 25
[1] 25
[1] 25
[1] 25

repeat循环

repeat是死循环,只有用break来打断
repeat{

break
}

举例

> i = 1
> repeat{
+   print (i^2)
+   i = i + 1
+   if (i>5) break
+ }
[1] 1
[1] 4
[1] 9
[1] 16
[1] 25

break、next

break是终止整个循环
next是终止当前的循环,不执行循环体中next后面的部分。

函数和包

1、函数

向量、因子、矩阵、数据框、数组、列表以及函数都是一类对象,可以随时创建,可以作为函数的参数。也就是说,R语言中的函数因为是一类对象,所以可以在函数中再创造函数,在C语言和C++等语言中函数就不是一类对象,必须提前编译。

1)、创建

在R语言中,没有return语句的时候,会把整个函数的最后一句作为返回语句。

myfunction = function(par1,par2){
……
}

> myadd = function(a,b,c){
+   return (a+b+c)
+ }
> (a = myadd(1,2,3))
[1] 6
> mystat = function(x,na.omit=FALSE){
+   if (na.omit){
+     x=x[!is.na(x)] #是否忽略向量中的缺省值
+   }
+   m=mean(x)
+   n=length(x)
+   s=sd(x)
+   skew=sum((x-m)^3/s^3)/n
+   return (list(n=n,mean=m,stdev=s,skew=skew))
+ }
> x=rnorm(1000,100,10) #创建一个正太分布的随机向量,有1000个数,平均数是100,标准差是10
> mystat(x)
$n
[1] 1000

$mean
[1] 100.4087

$stdev
[1] 9.899276

$skew
[1] 0.03952049
2)、查看函数代码
  • 不带括号的函数名
  • 使用page函数,打开编辑器查看代码。
> mystat  #通过不带括号的函数名来调用
mystat = function(x,na.omit=FALSE){
  if (na.omit){
    x=x[!is.na(x)] #是否忽略向量中的缺省值
  }
  m=mean(x)                 #调用mean()函数计算均值
  n=length(x)               #调用length()函数计算长度
  s=sd(x)                   #调用sa()函数计算标准差
  skew=sum((x-m)^3/s^3)/n   #计算偏度系数 偏度系数是描述分布偏离对称性程度的一个特征数。当分布左右对称时,偏度系数为0。当偏度系数大于0时,即重尾在右侧时,该分布为右偏。当偏度系数小于0时,即重尾在左侧时,该分布左偏。
  return (list(n=n,mean=m,stdev=s,skew=skew))
}
myadd = function(a,b,c){
  return (a+b+c)
}

>page(mystat) #使用page函数,调用系统的编辑器查看代码。
3)、导入.R文件
source(‘G:/TestFunction.r‘)

2、包的安装和加载

1)、包的安装

R语言中包的安装会自动解决依赖

使用R自带的编辑器安装包

  • 第一步、程序包 ————> 设定CRAN镜像
  • 第二步、程序包 ————> 安装程序包

使用命令安装

  • install.packages(‘abc’)
2)、包的加载

安装包的时候需要用”将包的名称包裹,加载包的时候不需要。

Rstudio中使用命令加载包

> library(abc)
载入需要的程辑包:abc.data
载入需要的程辑包:nnet
载入需要的程辑包:quantreg
载入需要的程辑包:SparseM

载入程辑包:‘SparseM’

The following object is masked from ‘package:base’:

    backsolve

载入需要的程辑包:MASS
载入需要的程辑包:locfit
locfit 1.5-9.1   2013-03-22
>

Rstudio中,使用右下角的面板来加载包。

直接勾选就好。

向量化计算

1、普通的加减乘除

所谓向量化运算就是对向量中的每一个元素都进行运算处理

举例

> (x=1:5)
[1] 1 2 3 4 5
> (x=x^2)
[1]  1  4  9 16 25
> (y=matrix(1:20,4,5))
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    5    9   13   17
[2,]    2    6   10   14   18
[3,]    3    7   11   15   19
[4,]    4    8   12   16   20
> (y=y^2)
     [,1] [,2] [,3] [,4] [,5]
[1,]    1   25   81  169  289
[2,]    4   36  100  196  324
[3,]    9   49  121  225  361
[4,]   16   64  144  256  400

> (y=11:15)
[1] 11 12 13 14 15
> (x+y) #相同长度的向量可以直接+-*/
[1] 12 16 22 30 40
> y>=13
[1] FALSE FALSE  TRUE  TRUE  TRUE

向量化运算支持哪些运算:+-*/等四则运算 >

2、apply家族

  • apply
  • sapply lapply
  • mapply tapply

    1)、 apply(x,MARGIN=2,…)

apply(数组,维度,函数/函数名)

沿着数组的某一维度来处理数据,利用设置MARGIN的值来改变数据。MARGIN=2表示在列(域)的层面上处理数据

举例

> x=data.frame(pv=rnorm(100,20,3), #先生成一个有三个域的数据框
>            + uv=rnorm(100,40,4),
>            + ip=runif(100,40,50))
> apply(x,MARGIN = 2,mean)  #MARGIN=1表示在行(记录)层面上处理数据,MARGIN=2表示在列(域)的层面上处理数据。处理方式是,mean,求均值。
      pv       uv       ip 
20.45526 39.81572 45.30480 
#quantile是查看一组数据的百分位点,probs=c(0.1,0.5,0.9)设置想查看的百分位点
> apply(x,MARGIN = 2,quantile,probs=c(0.1,0.5,0.9))  
          pv       uv       ip
10% 16.90155 35.17513 41.02527
50% 20.09723 39.38737 45.19671
90% 24.70416 44.82648 49.37066
#可以看到pv、uv、ip在0.1、0.5、0.9处的百分位点

#数据降维
> (x=array(rnorm(2*3*4),c(2,3,4))) #生成一个三维的列表
, , 1

            [,1]      [,2]       [,3]
[1,] -0.04255047 -1.407329 -0.9931210
[2,] -1.65621498  1.479997  0.5501781

, , 2

           [,1]      [,2]       [,3]
[1,] -0.4668323 0.7451938  0.9585998
[2,] -0.4205612 0.3414420 -1.1822220

, , 3

          [,1]     [,2]        [,3]
[1,]  0.596996 0.233922  0.03285836
[2,] -1.534795 1.598219 -1.89555578

, , 4

           [,1]       [,2]      [,3]
[1,]  0.6793028  0.4429203 -0.605179
[2,] -0.4042032 -0.6241099  1.257368

> apply(x,c(1,2),mean)  #将列表沿着3维的方向来处理数据,求均值。
          [,1]       [,2]       [,3]
[1,]  0.191729 0.00367673 -0.1517105
[2,] -1.003944 0.69888709 -0.3175580
> apply(x,c(1,3),mean)  #将列表沿着2维的方向来处理数据,求均值。
           [,1]       [,2]       [,3]       [,4]
[1,] -0.8143335  0.4123204  0.2879255 0.17234803
[2,]  0.1246534 -0.4204471 -0.6107106 0.07635149
> apply(x,c(2,3),mean)  #将列表沿着1维的方向来处理数据,求均值。
            [,1]       [,2]       [,3]        [,4]
[1,] -0.84938273 -0.4436968 -0.4688996  0.13754980
[2,]  0.03633396  0.5433179  0.9160706 -0.09059479
[3,] -0.22147144 -0.1118111 -0.9313487  0.32609427

2)、 lapply(列表,函数名/函数,其他参数)

lapply总是返回一个列表

> (x=list(a=1:10,b=c(11,21,31,41,51))) #创建一个列表
$a
 [1]  1  2  3  4  5  6  7  8  9 10

$b
[1] 11 21 31 41 51

> lapply(x,mean)  #对列表的成分求均值,lappy返回值也是一个列表。
$a
[1] 5.5

$b
[1] 31

> (x=1:4)
[1] 1 2 3 4

> lapply(x,runif) #runif函数是从均匀分布的总体中抽取若干个数字。runif函数一次作用于x中的每一个元素。
[[1]]
[1] 0.1420802 #x=1的时候抽出0.1420802 

[[2]]
[1] 0.5706941 0.5051777 #x等于2的时候,抽出两个数

[[3]]
[1] 0.9835877 0.5630008 0.2712130 #x等于3的时候,抽出3个数

[[4]]
[1] 0.3299968 0.6336621 0.3345203 0.4135361 #x等于4的时候,抽出4个数

> lapply(x,runif,min=0,max=100)
[[1]]
[1] 0.9995915

[[2]]
[1] 17.17236 85.43321

[[3]]
[1] 95.25653 52.58847 48.70183

[[4]]
[1] 79.50202 96.41646 56.94763 38.45675

> lapply(x,runif,min=0,max=100)  #min=0,max=100是作用于runif函数的。从0-100中间选择。
[[1]]
[1] 10.90927

[[2]]
[1] 13.579156  5.199927

[[3]]
[1] 74.93334 67.08987 91.84644

[[4]]
[1] 41.47904 90.65402 44.92566 79.38730

#在lapply中书写匿名函数获取列表中每个矩阵的第一行。
> (x=list(a=matrix(1:6,2,3),b=matrix(4:7,2,2)))
$a
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6

$b
     [,1] [,2]
[1,]    4    6
[2,]    5    7

> lapply(x,function(m) m[1,])
$a
[1] 1 3 5

$b
[1] 4 6
3)、 sapply(列表,函数名/函数,其他参数)

sapply和lapply的差不多,但是sapply可以自动化简函数,

  • 当结果列表长度为一的时候,返回向量。
  • 当结果列表长度相同且大于一的时候返回矩阵。
  • 当结果列表不等的时候仍然返回一个列表。
> (x=list(a=1:10,b=c(11,21,31,41,51)))
$a
 [1]  1  2  3  4  5  6  7  8  9 10

$b
[1] 11 21 31 41 51

> sapply(x,mean)  #返回结果变成了向量
   a    b 
 5.5 31.0 
> class(sapply(x,mean))
[1] "numeric"
4)、 mapply(列表,函数名/函数,其他参数)

mapply(函数/函数名,数据,函数相关的参数) ,mapply是apply的多元版本。

> (u=list(rep(1,4),rep(2,3),rep(3,2),rep(4,1)))
[[1]]
[1] 1 1 1 1

[[2]]
[1] 2 2 2

[[3]]
[1] 3 3

[[4]]
[1] 4

> (o=mapply(rep,1:4,4:1)) #4:1对应设置了前面的1:4重复次数,和上面的结果是一样的。
[[1]]
[1] 1 1 1 1

[[2]]
[1] 2 2 2

[[3]]
[1] 3 3

[[4]]
[1] 4

#自己写函数,再由mapply来调用
> s=function(n,mean,std){
+   rnorm(n,mean,std) #从均值为mean,标准差为std的总体里抽取n个元素。
+ }
> s(4,1,2) #测试函数
[1]  2.1789096  0.3389229  3.3318089 -2.4226340

#在mapply中调用自己写的函数,返回一个列表。
> mapply(s,1:5,5:1,2) #1:5表示一次抽取1,2,3,4,5个元素,5:1表示对应前面五次每次的均值,2表示,这5次抽取的每个总体的标准差。
[[1]]
[1] 4.89449  #从均值为5标准差为2的整体中随机抽取1[[2]]
[1] 2.465339 6.585427 #从均值为4标准差为2的整体中随机抽取2[[3]]
[1] 3.054207 1.269529 5.044077 #从均值为3标准差为2的整体中随机抽取3[[4]]
[1]  0.6101787  2.7211071  1.6095973 -0.4073418 #从均值为2标准差为2的整体中随机抽取4[[5]]
[1]  1.6578902  0.9364415 -2.8377756  2.5111859 -1.1535675 #从均值为1标准差为2的整体中随机抽取5个

list(s(1,5,2),s(2,4,2),s(3,3,2),s(4,2,2),s(5,1,2)) #效果和上面用mapply是一样的。
[[1]]
[1] 4.380181

[[2]]
[1] -1.345394  4.906018

[[3]]
[1]  2.7507204 -0.8917604  3.4670050

[[4]]
[1] 2.589484 3.014790 6.153610 2.452525

[[5]]
[1]  2.2042391 -1.9790139 -1.6326908  0.9025792  2.4117260
5)、 tapply(向量,因子/因子列表,函数/函数名)

向量的子集进行操作

 > (x=c(rnorm(5),runif(5),rnorm(5,1)))
 [1] -1.1003527 -0.6135971  0.9259782 -0.6880730 -1.1620147  0.5222504  0.6076465  0.6647177
 [9]  0.3104704  0.5861854  1.7122914  1.0757132  2.1427658  2.6782741 -1.0646930
> (f=gl(3,5))
 [1] 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3
Levels: 1 2 3
> tapply(x,f,mean) #对x这个向量按照f的水平因子进行求均值的操作,1下面是x中前5个数的均值,2下面是x中间5个数的均值,3下面是x中后面5个数的均值。
> 
         1          2          3 
-0.5276119  0.5382541  1.3088703 
> tapply(x,f,mean,simplify=FALSE) #tapply函数中simplify的默认值是TRUE,完成了简化,否则返回的也是一个列表。
$`1`
[1] -0.5276119

$`2`
[1] 0.5382541

$`3`
[1] 1.30887

3、split

  • 根据因子或者因子列表将向量或者其他对象进行分组操作
  • 通常与lappy一起使用
  • spilt(向量/列表/数据框,因子/因子列表)

一般split函数是和lapply/sapply函数配合使用的,lapply(split(x,f),mean),将x先按照f分组,再使用mean函数求均值,最后以列表的形式输出。

 > (x=c(rnorm(5),runif(5),rnorm(5,1)))
 [1] -1.1003527 -0.6135971  0.9259782 -0.6880730 -1.1620147  0.5222504  0.6076465  0.6647177
 [9]  0.3104704  0.5861854  1.7122914  1.0757132  2.1427658  2.6782741 -1.0646930

> f
 [1] 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3
Levels: 1 2 3

> split(x,f)  #将x根据f分成相应的组
$`1`
[1] -1.1003527 -0.6135971  0.9259782 -0.6880730 -1.1620147 #$`1`水1在x中对应的五个值

$`2`
[1] 0.5222504 0.6076465 0.6647177 0.3104704 0.5861854 #$`2`水2在x中对应的五个值

$`3`
[1]  1.712291  1.075713  2.142766  2.678274 -1.064693 #$`3`水3在x中对应的五个值

#将x先按照f分组,再使用mean函数求均值,最后以列表的形式输出。
> lapply(split(x,f),mean)
$`1`
[1] -0.5276119

$`2`
[1] 0.5382541 

$`3`
[1] 1.30887

# colMeans是计算列的平均值的函数
> lapply(s,function(x) colMeans(x[,c("Ozone","Wind","Temp")]))
$`5`
   Ozone     Wind     Temp 
      NA 11.62258 65.54839 

$`6`
   Ozone     Wind     Temp 
      NA 10.26667 79.10000 

$`7`
    Ozone      Wind      Temp 
       NA  8.941935 83.903226 

$`8`
    Ozone      Wind      Temp 
       NA  8.793548 83.967742 

$`9`
Ozone  Wind  Temp   
   NA 10.18 76.90 
#所有Ozone的均值都是NA,说明是有确实存在,所以导致计算列均值的时候也是缺失值。

> sapply(s,function(x) colMeans(x[,c("Ozone","Wind","Temp")],na.rm = TRUE)) 
             5        6         7         8        9
Ozone 23.61538 29.44444 59.115385 59.961538 31.44828
Wind  11.62258 10.26667  8.941935  8.793548 10.18000
Temp  65.54839 79.10000 83.903226 83.967742 76.90000
#设置sapply函数的na.rm属性为TRUE是可以忽略缺失值的。

#当然,比较6的做法是我们自己是我们自己手动清洗数据
> g=complete.cases(airquality) #第一步,调用complete.cases()清洗数据
> s_tmp=split(airquality[g,],airquality$Month) #第二步,调用split方法来将已经清洗过的数据根据月份来分组。
> sapply(s_tmp,function(x) colMeans(x[,c("Ozone","Wind","Temp")])) #调用sapply方法并且自己写一个匿名函数来求特定域的均值。
             5         6         7        8   9
Ozone 26.41935 53.666667 59.258065 21.42105 NaN
Wind  11.73871  8.803333  8.619355 10.95263 NaN
Temp  69.35484 83.066667 84.161290 72.84211 NaN

排序

  • sort:对向量进行排序,返回排好序的内容。
  • order:返回排序好的内容的下标/多个排序标准。
> (x=data.frame(v1=1:5,v2=c(10,7,9,6,8),v3=11:15,v4=c(1,1,2,2,1)))
  v1 v2 v3 v4
1  1 10 11  1
2  2  7 12  1
3  3  9 13  2
4  4  6 14  2
5  5  8 15  1
> (sort(x$v2)) #按升序排列
[1]  6  7  8  9 10
> (sort(x$v2,decreasing=TRUE)) #按降序排列
[1] 10  9  8  7  6
> order(x$v2) #order是返回下标的,不返回内容。
[1] 4 2 5 3 1
> x[order(x$v2),] #调用得到的下标打印
  v1 v2 v3 v4
4  4  6 14  2
2  2  7 12  1
5  5  8 15  1
3  3  9 13  2
1  1 10 11  1
> x[order(x$v4,x$v2),]  #先按照v4进行排序,v4中有相同的再按照v2进行排序。
  v1 v2 v3 v4
2  2  7 12  1
5  5  8 15  1
1  1 10 11  1
4  4  6 14  2
3  3  9 13  2
> x[order(x$v4,x$v2,decreasing=TRUE),] #降序排列。
  v1 v2 v3 v4
3  3  9 13  2
4  4  6 14  2
1  1 10 11  1
5  5  8 15  1
2  2  7 12  1

数据处理流程

原始数据(raw dataset) —> 预处理后的数据(clean dataset)

构建子集 subsetting

1、构建方法

  • [] 提取一个或者多类型相同的元素 R语言中下标是从1开始的。
  • [[]] 从列表或者数据框中提取数据
  • $按照名字从列表或者数据框中提取元素

举例

1. 设置条件进行子集提取

> (x=c(rnorm(20,5,3)))
 [1] -1.63156732  3.76807795  6.17118143  2.43515444  3.59313881  4.16966527  0.41943174  4.81982118  0.10841749
[10] 11.16069947  0.09089112  4.62378612  8.43299270  5.97803844  2.64061372  2.85256809  7.55771969  7.94601703
[19]  3.93132473  2.63224266

> x[x>5] #设置条件进行子集提取
[1]  6.171181 11.160699  8.432993  5.978038  7.557720  7.946017

> x>5 #直接输入x>5可以得到对向量中每个元素的大小的判断
 [1] FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE
[20] FALSE

> (y=1:5)
[1] 1 2 3 4 5
> y[y<=2|y>=4]
[1] 1 2 4 5
> y[-3]  #加负号代表将数据去除
[1] 1 2 4 5

以上是关于R语言笔记之语法篇的主要内容,如果未能解决你的问题,请参考以下文章

ORACLE官方SQL语言参考笔记之Oracle SQL简介篇(第一章)

从零开始系列-R语言基础学习笔记之二 数据结构

从零开始系列-R语言基础学习笔记之二 数据结构

ThinkPHP项目笔记之模板篇

R语言之merge举例

C语言篇 + 字符串处理函数和内存函数的介绍及模拟实现(避开你的语法坑,请注意查收)