笔记 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.0412
x <- 1:4
lapply(x, runif, min = 0, max = 10)## [[1]]
## [1] 3.38
##
## [[2]]
## [1] 0.99 2.56
##
## [[3]]
## [1] 6.70 3.73 2.75
##
## [[4]]
## [1] 7.24 3.12 5.71 4.85
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.500 -0.154 0.664 5.171
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] [,7] [,8] [,9] [,10]
## 25% -0.151 -1.026 -0.592 0.572 -0.0448 0.212 -0.7386 -1.142 1.02 -1.196
## 75% 0.334 -0.294 0.739 1.109 0.4642 1.269 0.0311 0.369 1.12 -0.662
a <- array(rnorm(2 * 2 * 10), c(2, 2, 10))
apply(a, c(1, 2), mean)## [,1] [,2]
## [1,] 0.2879 -0.722
## [2,] -0.0313 0.307
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.237 0.541 1.392
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.27
##
## $`2`
## [1] 0.4
##
## $`3`
## [1] 1.27
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.4 -1.78
## $ 1.2: num [1:2] -0.466 -1.052
## $ 1.3: num -0.879
## $ 2.3: num 0.347
## $ 2.4: num [1:2] 0.347 0.562
## $ 2.5: num [1:2] 1.352 -0.385
3.13.10 mapply
- 多变量版
apply从多个参数范围取值 并用函数得到结果
noise <- function(n, mean, sd) {
rnorm(n, mean, sd)
}
mapply(noise, 1:5, 1:5, 2)## [[1]]
## [1] 0.583
##
## [[2]]
## [1] 4.830 -0.594
##
## [[3]]
## [1] 5.04 1.91 6.05
##
## [[4]]
## [1] 6.70 8.37 1.54 2.93
##
## [[5]]
## [1] 6.94 7.13 8.67 7.12 4.71
#等同于如下循环
#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记录函数执行时被调用函数用时