R Programming笔记

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出版)
  • 更多书单

参考文档:

提问的方式:

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] "<!DOCTYPE html>"                                               
[2] "<html lang=\"en\">"                                            
[3] ""                                                              
[4] "<head>"                                                        
[5] "<meta charset=\"utf-8\" />"                                    
[6] "<title>Johns Hopkins Bloomberg School of Public Health</title>"

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()字符串转换为日期与时间格式

推荐阅读更多精彩内容