Week 1
1 参考书目 & 文档
参考书目:
- R Programming for Data Science
- Chambers (2008). Software for Data Analysis, Springer.
- Chambers (1998). Programming with Data, Springer.
- Venables & Ripley (2002). Modern Applied Statistics with S, Springer.
- Venables & Ripley (2000). S Programming, Springer.
- Pinheiro & Bates (2000). Mixed-Effects Models in S and S-PLUS, Springer.
- Murrell (2005). R Graphics, Chapman & Hall/CRC Press.
- Use R! 系列丛书(由Springer出版)
- 更多书单
参考文档:
- An Introduction to R(中文译本:R导论)
- Writing R Extensions(编写你自己的R包)
- R Data Import/Export(用多种方式导入导出数据)
- R Installation and Administration(通过代码安装R)
- R Internals(心脏不好不要看,R的底层实现细节)
提问的方式:
- 最佳提问标题样式:"R 3.0.2 lm() function on Mac OS X 10.9.1 -- seg fault on large data frame"
- How to ask questions the smart way(中文译文:提问的智慧)
2 控制台赋值与输出
##例一
> x <- 5
> print(x)
[1] 5
> x
[1] 5
##例二
> x <- 1:20
> x
[1] 1 2 3 4 5 6 7 8 9 10 11 12
[13] 13 14 15 16 17 18 19 20
3 数据类型
3.1 R对象及其属性
3.1.1 基本的五种对象类型
- 字符型(character)
- 数值型(实数和小数)(numeric)
- 整型(integer)
- 复数型(complex)
- 逻辑型(logical)
3.1.2 最基本的对象是向量(vector)
- 一个向量可以包含同一类型的多个对象
- 唯一的例外是列表(list)向量可以包含多个不同类型的对象
3.1.3 数值
- R里面几乎所有的数字都被作为双精度实数来处理(numeric)
- 如果你想要一个整型数,可以通过在数字后面加上L后缀来实现
- 特殊的值:Inf,表示无穷(infinity),可以像实数一样参与运算;示例:1 / 0 得到Inf;1 / Inf 得到0;同样的还有负无穷(-Inf)
- 特殊的值:NaN,表示非数值(not a number);示例:0 / 0 得到NaN
3.1.4 属性
不是所有R对象都必须有属性,但属性可以是对象的一部分:
- 名字(name),维度名字(dimname)
- 维度(dimensions)
- 类型(class)
- 长度(length)
- 其他用户定义的属性/元数据(attribute() 函数设定或者修改)
3.2 向量和列表(Vectors and Lists)
3.2.1 创建向量
使用c() 函数创建
> x <- c(0.5, 0.6) ##numeric
> x <- c(TRUE, FALSE) ##logical
> x <- c(T, F) ##logical
> x <- c("a", "b", "c") ##character
> x <- 9:29 ##integer
> x <- c(1+0i, 2+4i) ##comples
使用vector() 函数创建
> x <- vector("numeric", length = 10)
> x
[1] 0 0 0 0 0 0 0 0 0 0
3.2.2 混合对象
R会创建一个最低级公共类型(least common denominator)的向量,完成隐式类型转换。
> x <- c(1.7, "a") ##character
> x <- c(TRUE, 2) ##numeric
> x <- c("a", TRUE) ##character
3.2.3 显式强制转换
使用as.* 函数
> class(x)
[1] "integer"
> as.numeric(x)
[1] 0 1 2 3 4 5 6
> as.logical(x)
[1] FALSE TRUE TRUE TRUE TRUE TRUE TRUE
> as.character(x)
[1] "0" "1" "2" "3" "4" "5" "6"
> as.complex(x)
[1] 0+0i 1+0i 2+0i 3+0i 4+0i 5+0i 6+0i
转换失败返回NaN
> x <- c("a", "b", "c")
> as.numeric(x)
[1] NA NA NA
Warning message:
NAs introduced by coercion
> as.logical(x)
[1] NA NA NA
3.3 列表(List)
列表有索引,元素由双层中括号包围,这是把列表和其他向量区分的一个方法。
> x <- list(1, "a", TRUE, 1+4i)
> x
[[1]]
[1] 1
[[2]]
[1] "a"
[[3]]
[1] TRUE
[[4]]
[1] 1+4i
3.4 矩阵(Matrix)
矩阵是具有维度属性的向量,维度属性是一个长度为2的整型向量,其中第一个数字是矩阵的行数,第二个数字是矩阵的列数。
> m <- matrix(nrow = 2, ncol = 3)
> m
[,1] [,2] [,3]
[1,] NA NA NA
[2,] NA NA NA
> dim(m)
[1] 2 3
> attributes(m)
$dim
[1] 2 3
3.4.1 矩阵按列填充
> m <- matrix(1:6, nrow = 2, ncol = 3)
> m
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
3.4.2 矩阵可以通过给向量添加维度属性直接创建
> m <- 1:10
> m
[1] 1 2 3 4 5 6 7 8 9 10
> dim(m) <- c(2, 5)
> m
[,1] [,2] [,3] [,4] [,5]
[1,] 1 3 5 7 9
[2,] 2 4 6 8 10
3.4.3 列绑定和行绑定(cbind-ing and rbind-ing)
列绑定和行绑定可以通过调用函数cbind和rbind来实现
> x <- 1:3
> y <- 10:12
> cbind(x,y)
x y
[1,] 1 10
[2,] 2 11
[3,] 3 12
> rbind(x,y)
[,1] [,2] [,3]
x 1 2 3
y 10 11 12
3.5 因子(factor)
因子分为有序和无序两种.
unclass函数能够移除以一个向量的类型,显示因子的内部编码。
> x <- factor(c("yes", "yes", "no", "yes", "no" ))
> x
[1] yes yes no yes no
Levels: no yes
> table(x)
x
no yes
2 3
> unclass(x)
[1] 2 2 1 2 1
attr(,"levels")
[1] "no" "yes"
通过factor函数里的levels参数设定基线水平(默认按照字母排序)。
> x <- factor(c("yes", "yes", "no", "yes", "no"), levels = c("yes", "no"))
> x
[1] yes yes no yes no
Levels: yes no
3.6 缺失值
R里面的缺失值用NA或者NaN来表示,NaN用来表示未定义的数学运算,而NA则用来表示其他的缺失值。
- is.na() 用来检验对象是否NA
- is.nan() 用来检验对象是否NaN
- NA可能属于不同的类
- NaN属于NA,但NA并不一定是NaN值
3.7 数据框(data frame)
数据框用来存储表格数据。
- 数据框可以存储不同类型的元素。
- 数据框拥有特殊属性:row.names
- 可以通过调用read.table() 或read.csv() 来创建数据框
- 可以通过调用data.matrix() 函数来把一个数据框转换为矩阵(里面类型强制转换为同一种)
> x <- data.frame(foo = 1:4, bar = c(T, T, F, F))
> x
foo bar
1 1 TRUE
2 2 TRUE
3 3 FALSE
4 4 FALSE
> nrow(x)
[1] 4
> ncol(x)
[1] 2
3.8 名字属性(names)
可以给R对象指定名字
> x <- 1:3
> names(x)
NULL
> names(x) <- c("foo", "bar", "norf")
> x
foo bar norf
1 2 3
> names(x)
[1] "foo" "bar" "norf"
列表指定名字
> x <- list(a = 1, b = 2, c = 3)
> x
$a
[1] 1
$b
[1] 2
$c
[1] 3
矩阵指定名字
> m <- matrix(1:4, nrow = 2, ncol = 2)
> dimnames(m) <- list(c("a", "b"), c("c", "d"))
> m
c d
a 1 3
b 2 4
4 读写数据
4.1 读取数据
- read.table(), read.csv() 是两种常见的读取数据的函数,返回一个数据框
- readLines() 用于逐行读取文本文件
- source() 读取R代码
- dget() 读取R代码(逆句法分析)
- load() 和unserialize() 用于把二进制对象读入R
4.2 写入数据
- write.table()
- writhLines()
- dump()
- dput()
- save()
- serialize()
4.3 最常用read.table() 函数读取数据
重要的参数用途:
- file, 文件或者链接的名称
- header, 逻辑标志,表明第一行是否表头(read.csv默认为TRUE)
- sep, 分隔符,是一个字符串,默认空格(read.csv默认逗号)
- colClasses, 字符向量,长度与数据集列数相等,表示每一列的数据类型
- nrows, 数据的行数
- comment.char, 表明文件中用于注释的字符,是一个字符串,默认是井号
- skip, 指定了从文件开头往下忽略多少行
- stringsAsFactors, 默认TRUE, 选择是否把字符变量编码为因子
4.4 使用read.table() 读取大数据
- 阅读read.table() 的帮助页面,有许多重要信息
- 大致计算数据的容量,以了解电脑是否有足够内存存储
- 如果文件没有注释,把comment.char设为空(= "")
- 设置colClasses参数,这样R就不用逐列扫描
- 可以设定nrows参数先读取前100或1000行,再用sapply() 遍历每一列,并调用class() 告诉你每一列的数据类型(sapply(initial, class)),把这个信息存储起来用来指定colClasses参数
- 使用nrows参数R就不用边读取边计算了,即使估计的行数比实际稍多也没有关系
4.5 文本格式
- 两个主要的输出数据的函数是dump() 和dput() ,包含更多元数据,比如类和对象中的数据类型
- source() 和dget() 函数可以读取未经dump() dput() 输出的数据
- dput() 接受绝大部分单一R对象,生成R代码从头重新构建R对象
> y <- data.frame(a = 1, b = "a")
> dput(y)
structure(list(a = 1, b = structure(1L, .Label = "a", class = "factor")), .Names = c("a",
"b"), row.names = c(NA, -1L), class = "data.frame")
> dput(y, file = "y.R")
> new.y <- dget("y.R")
> new.y
a b
1 1 a
- dget() 可以作用于多个R对象
> x <- "foo"
> y <- data.frame(a = 1, b = "a")
> dump(c("x", "y"), file = "data.R")
> rm(x, y)
> source("data.R")
> y
a b
1 1 a
> x
[1] "foo"
5 联系(connection)
5.1 与外界的接口
- file() ,打开一个无压缩文件
- gzfile() 和bzfile() ,打开压缩文件
- url() ,连接网页
5.2 file() 函数的参数
- description参数是文件名
- open参数需要有一个标识:
- "r"表示读取(reading)
- "w"表示写入(writing)
- "a"表示附加(appending)
- "rb", "wb", "ab"表示读取、写入和附加二进制文件
5.3 逐行读取网页
> con <- url("http://www.jhsph.edu", "r")
> x <- readLines(con)
> head(x)
[1] ""
[2] ""
[3] ""
[4] ""
[5] ""
[6] "Johns Hopkins Bloomberg School of Public Health "
6 提取子集
6.1 一般方法
- [ 返回的对象和原来相同,可以返回多个元素
- [[ 提取列表或这数据框里的一个元素
- $ 根据name提取一个元素
> x <- c("a", "b", "c", "d", "a")
> x[1]
[1] "a"
> x[2]
[1] "b"
> x[1:4]
[1] "a" "b" "c" "d"
> x[x > "a"]
[1] "b" "c" "d"
> u <- x>"a"
> u
[1] FALSE TRUE TRUE TRUE FALSE
> x[u]
[1] "b" "c" "d"
6.2 list取子集
> x <- list(foo = 1:4, bar = 0.6)
> x[1]
$foo
[1] 1 2 3 4
> x[[1]]
[1] 1 2 3 4
> x$bar
[1] 0.6
> x[["bar"]]
[1] 0.6
> x["bar"]
$bar
[1] 0.6
> x[c(1,2)]
$foo
[1] 1 2 3 4
$bar
[1] 0.6
> name <- "foo"
> x[[name]]
[1] 1 2 3 4
> x$name ##美元符号不能计算索引
NULL
[[可以递归取数
> x <- list(a = list(10, 12, 14), b = c(3.14, 2.81))
> x[[c(1,3)]]
[1] 14
> x[[c(2,1)]]
[1] 3.14
6.3 矩阵取子集
取值返回对矩阵有例外:默认返回一个向量而非1x1矩阵,可以通过参数关掉。
> x <- matrix(1:6, 2, 3)
> x[1,2]
[1] 3
> x[2,1]
[1] 2
> x[1,]
[1] 1 3 5
> x[,2]
[1] 3 4
> x[1, 2, drop = FALSE]
[,1]
[1,] 3
6.4 模糊匹配
$支持名字模糊匹配,[[需要设置exact参数
> x <- list(aardvark = 1:5)
> x$a
[1] 1 2 3 4 5
> x[["a"]]
NULL
> x[["a", exact = FALSE]]
[1] 1 2 3 4 5
6.5 移除缺失值
> x <- c(1, 2, NA, 4, NA, 5)
> bad <- is.na(x)
> x[!bad]
[1] 1 2 4 5
> y <- c("a", "b", NA, "d", NA, "f")
> good <- complete.cases(x,y)
> good
[1] TRUE TRUE FALSE TRUE FALSE TRUE
> x[good]
[1] 1 2 4 5
> y[good]
[1] "a" "b" "d" "f"
还可以通过complete.cases函数移除数据框缺失值
> airquality[1:6, 1] ##数据略
> good <- complete.cases(airquality)
> airquality[good, ][1:6, ] ##数据略
7 向量化运算
事件是可以并行的,不用循环就可以实现。
> x <- 1:4; y <- 6:9
> x + y
[1] 7 9 11 13
> x > 2
[1] FALSE FALSE TRUE TRUE
> x >= 2
[1] FALSE TRUE TRUE TRUE
> y == 8
[1] FALSE FALSE TRUE FALSE
> x * y
[1] 6 14 24 36
> x / y
[1] 0.1666667 0.2857143 0.3750000 0.4444444
矩阵乘法要加%%
> x <- matrix(1:4, 2, 2); y <- matrix(rep(10, 4), 2, 2)
> x * y
[,1] [,2]
[1,] 10 30
[2,] 20 40
> x / y
[,1] [,2]
[1,] 0.1 0.3
[2,] 0.2 0.4
> x %*% y
[,1] [,2]
[1,] 40 40
[2,] 60 60
Week 2
1 控制结构语句(Control Structures)
1.1 If-else
可以直接给变量用if-else语句赋值
y <- if(x > 3) {
10
} else {
0
}
1.2 For
- seq_along()返回和对象等长的数列
for(i in 1:10) {
print(x[i])
}
for(i in seq_along(x)) {
print(x[i])
}
for(letter in x ) {
print(letter)
}
for(i in seq_len(nrow(x))) {
for(j in seq_len(ncol(x))) {
print(x[i, j])
}
}
- 嵌套for循环(最好不要超过三层)
x <- matrix(1:6, 2, 3)
for (i in seq_len(nrow(x)) {
for (j in seq_len(ncol(x))) {
print(x[i, j])
}
}
1.3 While
- rbinom()正态分布随机数的生成函数:rnorm(n,mean=0,sd=1) 其中n表示生成的随机数数量,mean是正态分布的均值,默认为0,sd是正态分布的标准差,默认时为1
z <- 5
while (z >=3 && z <=10) {
print(z)
coin <- rbinom(1, 1, 0.5)
if (coin == 1) { ##random walk
z <- z+1
} else {
z <- z-1
}
}
1.4 Repeat
- 退出一个重复循环唯一的方式是调用break
1.5 Next
- next用来跳过一些迭代
for (i in 1:100) {
if (i <=20) {
##skip the first 20 iterations
next
}
## do something here
}
1.6 Return
- 退出循环并返回一个值
2 编写R函数
- 所有R函数会自动返回最后一个表达式的值
- 参数定义时可以设定缺省值
above <- function(x, n = 10) { ##默认参数等于10
use <- x >n
x[use]
}
columnmean <- function(y, removeNA = TRUE) {
nc <- ncol(y) ## 数据类型integer
means <- numeric(nc) ## 转化为numeric
for (i in 1:nc) {
means[i] <- mean(y[,i], na.rm = removeNA)
}
means
}
- R函数检查参数匹配的顺序:名称完全匹配、名称部分匹配、位置匹配
2.1 "..."参数
- "..."参数用来表明一些可以传递给另一个函数的参数(另一用法是用在泛型函数中)
myplot <- function(x, y, type = "1", ...) {
plot(x, y, type = type, ...)
}
- 无法确定参数数量的时候也用"..."
> args(paste)
function (..., sep = " ", collapse = NULL)
> args(cat)
function (..., file = "", sep = " ", fill = FALSE, labels = NULL,
append = FALSE)
- 任何出现在"..."之后的参数需要明确地给出名称,而且不能进行部分匹配
3 作用域规则
- 搜索顺序全局环境->包
make.power <- function(n) {
pow <- function(x) {
x^n
}
pow
}
> cube <- make.power(3)
> square <- make.power(2)
> cube(3)
[1] 27
> square(3)
[1] 9
> ls(environment(cube))
[1] "n" "pow"
> get("n", environment(cube))
[1] 3
y <- 10
f <- function(x) {
y <- 2
y^2 + g(x)
}
g <- function(x) {
x*y
}
> f(3)
[1] 34
- 作用域规则在统计学中的优化也很有用(暂略,具体看课程视频)
时间与日期
- R里面存储日期的数据类型是Date
> x <- as.Date("1970-01-01")
> x
[1] "1970-01-01"
> class(x)
[1] "Date"
> unclass(x)
[1] 0
> unclass(as.Date("1970-01-02"))
[1] 1
- R里面存储时间的数据类型是POSIXct和POSIXIt
> x <- Sys.time()
> x
[1] "2017-11-18 15:10:32 CST"
> p <- as.POSIXlt(x)
> names(unclass(p))
[1] "sec" "min" "hour"
[4] "mday" "mon" "year"
[7] "wday" "yday" "isdst"
[10] "zone" "gmtoff"
> p$sec
[1] 32.1765
- 对时间和日期起作用的函数:weekdays()返回一周中的某一天、months()返回月份、quarters()返回季度("Q1", "Q2", "Q3", "Q4")
- strptime()字符串转换为日期与时间格式