笔记 3 R语言编程
3.1 R语言概述
- R语言是S语言的一种方言
 - 1976年S是John Chambers等在贝尔实验室作为Fortran的扩展库开发出来的
 - 1988年用C语言重写 S3方法 白皮书
 - 1993年StatSci从贝尔实验室获得S语言的独家开发售卖许可
 - 1998年S4方法 绿皮书 之后S语言稳定 获得Association for Computing Machinery’s Software System Award
 - 2004年Insightful(原StatSci)从Lucent收购了S语言
 - 2006年Alcatel收购了Lucent成立Alcatel-Lucent
 - 2008年TIBCO收购Insightful 之前Insightful开发并售卖S-PLUS
 - 1991年Ross Ihaka与Robert GentlemanNew在Zealand开发了R
 - 1993年发布R第一份许可
 - 1995年R作为自由软件发放GUN许可
 - 1996年R邮件列表创立
 - 1997年R Core成立 控制R源码
 - 2000年R version 1.0.0 放出
 - 2013年R version 3.0.2 放出
 - R由CRAN掌控的base包与其他包组成
 - 其余参考R主页
 
3.2 获得帮助
help()
?command
# 提问给出以下信息
version
str(.Platform)3.3 数据类型及基本运算
- 所有数据都是对象 所有对象都有类型
 - 基本类型包括:字符“” 数字 整数L 复数(
Re实部Im虚部) 逻辑 - 向量储存同一类型数据
 - list存储不同类型数据 
[[*]]引用相应向量unlist可用做紧凑输出 - 对象可以有属性
attributes - 对象赋值符号为 <- 赋值同时展示加括号或直接输入对象名 可累加赋值 
a <- b <- c #表示注释 不执行:用来产生整数序列 也可以用seq生成- 向量用
c产生 - 空向量用
vector()函数建立 - 向量中类型不同的对象元素会被强制转换为同一类型 字符优先级最高 其次数字 其次逻辑(0 or 1) 也可以用来串联字符
 - 可使用
as.*来强制转化数据类型 - 对象可以用
names命名 - 变量名开头不能是数字和. 大小写敏感 下划线不要出现在名字里 分割用. 变量名中不能有空格
 - 保留字符
 
FALSE Inf NA NaN NULL TRUE break else for function if in next repeat while- 清空
rm(list = ls()) - 矩阵
 - 带有
dimension属性的向量为矩阵 矩阵的生成次序为upper-left matrix(1:6,nrow=2,ncol=3)表示建一个2行3列矩阵 从1到6 先列后行赋值 可用byrow = T来更改- 可用
c给dim赋值行和列数 这样可把一个向量转为一个矩阵m<-1:6;dim(m)<-c(2,3) - 矩阵可以用
rbind或cbind生成 t对矩阵转置- 因子变量表示分类数据 用标签名区分 用
level来命名排序 默认是字母排序 有些函数对顺序敏感可用levels = c()来命名 ( 例如低中高的排序 ) 数字表示drop = T表示显示截取数据的水平nlevels给出个数 - NaN表未定义或缺失值 NA表示无意义转换或缺失值 NaN可以是NA反之不可以 NA有数据类型 is.NaN与is.NA 可用来检验
 - 数据框
 - 特殊list 每个元素长度相等
 - 每一列类型相同 矩阵所有数据类型相同
 - 特殊属性
row.names - 转为矩阵
data.matrix - 变量名自动转化 可以不同
 - 因子变量保持为字符可以用 
Idata.frame(x,y,I(c)) - 数组
 - 表示更高维度的数据
 dim() = c(x,y,z)三维数组表示一组数dimnames给数组命名- 数组调用如果只有一行 需要
drop = F否则 不会按照数组分类 ts产生时间序列对象.Last.value引用前一个数值- 取整数 用
round(x,n)n表示保留几位小数 - 截取整数 
trunc - 开平方 
sqrt - 绝对值 
abs - 指数函数 
exp - 自然对数函数 
log - 以 10 为底的对数函数 
log10 - 三角函数 
sin cos tan asin acos atan - 常用的逻辑运算符有: 大于 
>小于<等于==小于或等于<=大于或等于>=与&非!或| - 判断向量x中是否与y中元素相等 
x %in% y结果返回逻辑值 sum求和prod求连乘range给极值范围duplicated给出有重复的值unique给出无重复的值- 向量操作 
union并集intersect交集setdiff除了交集的部分 rep用向量循环生成向量
x <- 1:4 # puts c(1,2,3,4) into x
i <- rep(2, 4) # puts c(2,2,2,2) into i
y <- rep(x, 2) # puts c(1,2,3,4,1,2,3,4) into y
z <- rep(x, i) # puts c(1,1,2,2,3,3,4,4) into z
w <- rep(x, x) # puts c(1,2,2,3,3,3,4,4,4,4) into w- 整型变量后面加上L x<-10L
 - Inf代表1/0 同样1/Inf运算结果为0
 
3.4 环境/文件操作
getwd()setwd()设置工作目录ls()列举环境中bianlianglist.files()或dir()列举当前目录下文件args()列举函数默认变量dir.create()创建文件目录 加上recursive=T可创建多级目录file.create()创建文件file.exists()检查文件是否存在file.info()检查文件信息file.rename()文件重命名file.copy()文件复制file.path()文件路径 多个文件组成多级路径unlink()删除文件
3.5 截取数据
[]截取数据- 可以用
[x,y]提取特定数值 [-1,-2]可剔除第一行第二列[[]]用来从list或者frame里提取元素 类型固定 可提取序列x[[1]][[3]]可部分匹配exact=FALSE- $用名字提取元素 可部分匹配
 - 提取矩阵时默认只能提取向量 但可以提取1*1矩阵
x[1,2,drop=FALSE] - 先用
is.NA()提取 用!排除 缺失值可用is.element(x,y)来处理很多表示NA值的数字 返回x %in% y的逻辑值 - 用
complete.cases()提取有效数据用[]提取可用数据 head(x,n)n表示从头截取多少行tail(x,n)n表示从尾截取多少行subset(x,f)x表示数据 f表示表达式- 条件筛选中获得一个变量多个数值的数据使用 
[is.element(x,c(' ',' ',' ')),]或者[x%in%c(' ',' ',' '),]使用x == c( ' ' , ' ' , ' ' )会报错 循环查找三个变量 x!='t'可能会把空白值输入 应该使用is.element(x,'t')ifelse(con,yes,no)利用条件筛选 返回yes 或者no 的值- 支持正则表达式
 
3.6 读取数据
read.tableread.csv读取表格 反之write.tablereadLines读取文本行 反之writeLinessource读取R代码 反之dumpdget读取多个R代码 反之dputload读取保存的工作区 反之saveunserialize读取二进制R对象 反之serialize?read.table- 大数据读取提速
 - 计算内存
 comment.char = ""不扫描注释- 设定
nrows - 设定
colClasses 
initial <- read.table("datatable.txt", nrows = 100)
classes <- sapply(initial, class)
tabAll <- read.table("datatable.txt",
                     colClasses = classes)- 使用
connections与file等保存外部文件指向 
3.7 控制结构
if else条件
if(<condition>) {
        ## do something
} else {
        ## do something else
}
if(<condition1>) {
        ## do something
} else if(<condition2>)  {
        ## do something different
} else {
        ## do something different
}- `for‵ 执行固定次数的循环 嵌套不超过2层
 
for(i in 1:10) {
        print(i)
}while条件为真执行循环 条件从左到右执行
count <- 0
while(count < 10) {
        print(count)
        count <- count + 1
}repeat执行无限循环 配合break中断并跳出循环next跳出当前循环继续执行
for(i in 1:100) {
        if(i <= 20) {
                ## Skip the first 20 iterations
                next 
        }
        ## Do something here
}return退出函数- 避免使用无限循环 可用
apply替代 
3.8 函数
f <- function(<arguments>) {
        ## Do something interesting
}- 函数中参数默认值可用
formals()显示 - 参数匹配
 - 先检查命名参数
 - 然后检查部分匹配
 - 最后检查位置匹配
 - 定义函数时可以定义默认值或者设为
NULL - 懒惰执行:只执行需要执行的语句
 ...向其他函数传参 之后参数不可部分匹配
3.9 编程标准
- 使用文本文档与文本编辑器
 - 使用缩进
 - 限制代码行宽 80为宜
 - 限制单个函数长度
 
3.10 范围规则
- 自由变量采用静态搜索
 - 环境是由数值符号对组成 每个环境都有母环境
 - 函数与环境组成环境闭包
 - 首先从函数环境中寻找变量
 - 之后搜索母环境
 - 最高层为工作区
 - 之后按搜寻列表从扩展包中寻找变量
 - 最后为空环境 之后报错
 - 可以函数内定义函数
 - S都存在工作区 函数定义一致 R存在内存 可根据需要调用函数环境
 
3.11 向量化操作
- 向量操作针对元素
 - 矩阵操作也针对元素 
%*%表示矩阵操作 
3.12 日期与时间
- 日期以
data类型存储 - 时间以
POSIXct或POSIXlt类型存储 - 数字上是从1970-01-01以来的天数或秒数
 POSIXct以整数存储时间POSIXlt以年月日时分秒等信息存储时间strptimeas.Dateas.POSIXltas.POSIXct用来更改字符为时间
3.13 循环
3.13.1 lapply
- 对列表对象元素应用函数
 - 可配合匿名函数使用
 
x <- list(a = 1:5, b = rnorm(10))
lapply(x, mean)## $a
## [1] 3
## 
## $b
## [1] -0.01965689
x <- 1:4
lapply(x, runif, min = 0, max = 10)## [[1]]
## [1] 6.572756
## 
## [[2]]
## [1] 2.2621469 0.1381539
## 
## [[3]]
## [1] 6.966633 5.325368 7.474903
## 
## [[4]]
## [1] 4.173194 7.207813 2.898582 1.067057
x <- list(a = matrix(1:4, 2, 2), b = matrix(1:6, 3, 2))
lapply(x, function(elt) elt[,1])## $a
## [1] 1 2
## 
## $b
## [1] 1 2 3
3.13.2 sapply
lapply的精简版- 如果结果是单元素列表 转化为向量
 - 如果结果是等长向量 转化为矩阵
 - 否则输出依旧为列表
 
x <- list(a = 1:4, b = rnorm(10), c = rnorm(20, 1), d = rnorm(100, 5))
sapply(x, mean)##          a          b          c          d 
##  2.5000000 -0.1692291  0.9700852  5.1580245
3.13.3 vapply
- 类似
lapply可用更复杂函数 返回矩阵 
3.13.4 replicate
- 用于将函数循环使用 如返回随机矩阵
 
3.13.5 rapply
- 用
how来调整输出方法 如选取某列表中类型数据进行迭代 
3.13.6 apply
- 数组边际函数 常用于矩阵的行列处理
 - 行为1,列为2
 - 可用
rowSumsrowMeanscolSumscolMeans来替代 大数据量更快 
x <- matrix(rnorm(50), 10, 5)
apply(x, 1, quantile, probs = c(0.25, 0.75))##           [,1]       [,2]       [,3]      [,4]       [,5]       [,6]
## 25% -1.2458330 -0.5414212 -0.1120456 0.1012263 -1.3165064 -1.1816281
## 75%  0.6162971 -0.3368592  0.9921388 0.4119842  0.8433195 -0.8027429
##            [,7]      [,8]         [,9]     [,10]
## 25% -0.96305282 0.3066211 -1.127146475 0.1568941
## 75% -0.03210668 0.5570227 -0.004091008 0.9914650
a <- array(rnorm(2 * 2 * 10), c(2, 2, 10))
apply(a, c(1, 2), mean)##            [,1]        [,2]
## [1,] -0.1434399 -0.60772656
## [2,]  0.1105775 -0.02336847
3.13.7 tapply
- 对数据子集(因子变量区分)向量应用函数
 
x <- c(rnorm(10), runif(10), rnorm(10, 1))
f <- gl(3, 10)
tapply(x, f, mean)##         1         2         3 
## 0.5827134 0.5174663 1.2768232
3.13.8 by
- 对数据按照因子变量应用函数 类似
tapply - 按照某个分类变量a分类求均值 
by(x[,-a],a,mean) 
3.13.9 split
- 将数据按因子分割为列表 常配合
lapply使用 - 类似
tapply - 可用来生成分组 用
drop来删除空分组 
x <- c(rnorm(10), runif(10), rnorm(10, 1))
f <- gl(3, 10)
lapply(split(x, f), mean)## $`1`
## [1] 0.287316
## 
## $`2`
## [1] 0.3564097
## 
## $`3`
## [1] 0.6582539
x <- rnorm(10)
f1 <- gl(2, 5)
f2 <- gl(5, 2)
str(split(x, list(f1, f2), drop = TRUE))## List of 6
##  $ 1.1: num [1:2] 1.627 0.199
##  $ 1.2: num [1:2] 0.126 0.291
##  $ 1.3: num -0.234
##  $ 2.3: num 1.15
##  $ 2.4: num [1:2] 0.0243 -0.1204
##  $ 2.5: num [1:2] 1.33 -1.3
3.13.10 mapply
- 多变量版
apply从多个参数范围取值 并用函数得到结果 
noise <- function(n, mean, sd) {
  rnorm(n, mean, sd)
}
mapply(noise, 1:5, 1:5, 2)## [[1]]
## [1] 0.765151
## 
## [[2]]
## [1] 2.454106 1.190829
## 
## [[3]]
## [1] 2.613718 5.184691 2.294388
## 
## [[4]]
## [1] 4.68462416 4.28984533 0.05776833 3.60456151
## 
## [[5]]
## [1] 7.444397 4.635312 5.087859 3.633820 8.159466
#等同于如下循环
#list(noise(1, 1, 2), noise(2, 2, 2),
#    noise(3, 3, 2), noise(4, 4, 2),
#    noise(5, 5, 2))3.13.11 eapply
- 对环境变量应用函数 用于包
 
3.14 模拟
- 在某分布下产生随机数
 - d 分布概率密度
 - r 分布随机数
 - p 分布累计概率
 - q 分布分位数
 
dnorm(x, mean = 0, sd = 1, log = FALSE)
pnorm(q, mean = 0, sd = 1, lower.tail = TRUE, log.p = FALSE)
qnorm(p, mean = 0, sd = 1, lower.tail = TRUE, log.p = FALSE)
rnorm(n, mean = 0, sd = 1)set.seed保证重现性sample对数据采样
3.15 调试
- 三种提示 
messagewarningerror只有error致命 - 关注重现性
 - 调试工具 
tracebackdebugbrowsertracerecover - 三思而行
 
3.16 分析代码
- 先设计 后优化
 system.time计算代码运行时间 返回对象类型proc_time- ‵user time` 执行代码用时
 system timeCPU时间elapsed time实际用时- 在多核或并行条件下实际用时可以短于执行代码用时
 - 明确知道耗时较长的函数时使用
 RprofR代码要支持分析函数summaryRprof可使结果易读- 不要与
system.time混用 - 0.02s记录一次执行函数
 by.total记录单个函数用时by.self记录函数执行时被调用函数用时