笔记 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
- 变量名自动转化 可以不同
- 因子变量保持为字符可以用
I
data.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.table
read.csv
读取表格 反之write.table
readLines
读取文本行 反之writeLines
source
读取R代码 反之dump
dget
读取多个R代码 反之dput
load
读取保存的工作区 反之save
unserialize
读取二进制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
以年月日时分秒等信息存储时间strptime
as.Date
as.POSIXlt
as.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
- 可用
rowSums
rowMeans
colSums
colMeans
来替代 大数据量更快
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 调试
- 三种提示
message
warning
error
只有error
致命 - 关注重现性
- 调试工具
traceback
debug
browser
trace
recover
- 三思而行
3.16 分析代码
- 先设计 后优化
system.time
计算代码运行时间 返回对象类型proc_time
- ‵user time` 执行代码用时
system time
CPU时间elapsed time
实际用时- 在多核或并行条件下实际用时可以短于执行代码用时
- 明确知道耗时较长的函数时使用
Rprof
R代码要支持分析函数summaryRprof
可使结果易读- 不要与
system.time
混用 - 0.02s记录一次执行函数
by.total
记录单个函数用时by.self
记录函数执行时被调用函数用时