2016年4月6日

基础入门

摘要:讲解R的基本操作知识,了解R的特点、资源获取方式,并掌握基本的程序编写

  • 什么是 R
  • 如何学习 R
  • 如何得到帮助,相关资源和书籍
  • RStudio,扩展包,工作空间
  • 数据对象
  • 向量化操作
  • 函数和控制语句

R 语言的介绍和学习资源

什么是 R

  • R 语言是一种业界盛行的数据分析编程语言
  • 理念就是快速、准确地把想法转化成软件
  • R 语言脱胎于 1980 年左右诞生的 S 语言
  • S语言是贝尔实验室统计研究部编制的一套完整的高级语言系统
  • 在1998年被美国计算机协会(ACM) 授予了“软件系统奖”
  • 1997 年 R 语言正式成为 GNU 项目
  • 2010年获得第一届“统计计算及图形奖”(美国统计协会)

R 语言的特点

  • 开源和免费
  • 功能强大且扩展性强
  • 与其它软件的交互能力强
  • 各类前沿的数据分析建模方法
  • 实现可重复性(Reproducible)分析
  • 适用于多操作系统的轻量化平台
  • 编程简单
  • 更新快速且文档完备

R 的整合能力

  • 数据:可连接数据库,如Oracle、MySQL
  • 运算:可调用C或Fortran函数进行底层运算
  • 应用:可作为运算引擎嵌入到JAVA开发的系统中(Rserve)
  • 网络:R与web整合部署(Rook, shiny)

R 的弱点

  • 解释型语言
  • 数据全部读入内存
  • 单线程

改进效能的方法

  • 善用R的语法
  • 升级硬件
  • 使用64位系统
  • 租用云计算(EC2)
  • compile预编译
  • 调用C或Fortran
  • 并行计算、MapReduce、RHadoop

请关注R语言大规模数据分析实战

和其它软件的对比

SPSS、SAS、Stata

  • 图形用户界面,无需写代码
  • 局限于已有算法
  • 不适合可重复分析

Matlab

  • 数值运算能力强
  • 通常用于命令行交互
  • 商业软件不利于整合其它软件

Python(NumPy/SciPy)

  • 功能全面,自由度高
  • 要求很强的能力

R 可以做什么?

学习 R 的方法

  • 在阅读时做笔记,以记下一些重点或心得
  • 在阅读代码时,要在 R 软件中亲手键入代码并理解其意义
  • 坚持练习,尝试利用身边的数据进行应用分析
  • 理解扩展包和函数背后的原理

学习 R 的资源(网络)

学习 R 的资源(书籍)

初学入门:

  • 《R in Action》
  • 《The Art of R Programming》

统计进阶:

  • 《A Handbook of Statistical Analyses_Using_R》
  • 《Modern Applied Statistics With S》

科学计算:

  • 《Introduction to Scientific Programming and Simulation Using R》

数据挖掘:

  • 《Data Mining with R: Learning with Case Studies》
  • 《An Introduction to Statistical Learning》

学习 R 的资源(书籍)

数据绘图:

  • 《ggplot2 Elegant Graphics for Data Analysis》

参考手册:

  • 《R Cookbook》
  • 《R in a Nutshell》

高级编程:

  • 《R Programming for Bioinformatics》
  • 《software for data analysis programming with R》

《数据科学中的R语言》

R 的下载和安装

RStudio的介绍

  • RStudio的界面直观而简洁
  • 细节设计非常方便
  • 支持在文档中混编代码

如何得到帮助

  • help.start() 打开帮助文档首页
  • help("foo")?foo 查看函数foo的帮助(引号可以省略)
  • help.search("foo")??foo 以foo为关键词搜索本地帮助文档
  • example("foo") 函数foo的使用示例(引号可以省略)
  • RSiteSearch("foo") 以foo为关键词搜索在线文档和邮件列表存档
  • apropos("foo", mode="function") 列出名称中含有foo的所有可用函
  • data() 列出当前已加载包中所含的所有可用示例数据集
  • vignette() 列出当前已安装包中所有可用的vignette文档
  • vignette("foo")为主题foo显示指定的vignette文档

工作目录和工作空间

工作目录

  • getwd() 显示当前的工作目录
  • setwd() 修改当前的工作目录

工作空间

  • ls() 列出当前工作空间中的对象
  • rm(objectlist) 移除(删除)一个或多个对象
  • save.image("myfile") 保存工作空间到文件myfile中(默认后缀 .RData)
  • save(object, file="myfile") 保存指定对象到一个文件中
  • load("myfile")读取一个工作空间到当前会话中

R 的启动设置

改变语言环境

  • (win)修改R安装目录下etc\Rconsole文件,language = en
  • (linux)在用户主目录中增加文件.RenvironLANGUAGE=en

改变默认工作目录 setwd("D:/work")

运行R 代码的方式

  • 在R 环境中运行,source()函数
  • 在shell使用Rscript 来运行R代码。 Rscript d:\rspace\example.R
  • 用REST、TCP/IP等协议来交换信息。
  • R的运算结果存为xml或json或csv或直接写到数据库中,然后外部程序再去读取。
  • R与其他编程语言的对象,相互直接生成。

R 语言快速入门

对象

向量及其基本操作

1 + 1 * 3
c(0,1,1,2,3,9)
c("hello world", "I am a R user")
c(1,2,3,4) + c(3,4,5,6)
c(1,2,3,4) + c(1,2)
1:6

对象

向量之间除了四种数字运算外,还可以进行比较,例如:

c(1,2,3,4) > c(1,2,1,2)
## [1] FALSE FALSE  TRUE  TRUE

函数

在R语言中,所有的操作和运算都是由函数来完成的。和数学中的函数类似,大多数的函数都是由函数名和参数这两项组成的。例如下面计算指数的例子,exp是函数名,括号中的1则是参数。

exp(1)
## [1] 2.718282
exp(c(1,2,3,4))
## [1]  2.718282  7.389056 20.085537 54.598150

变量

R语言中可以将各种向量赋值为一个变量。这种赋值操作符就是等号“=”,也可以使用"<-"。下面的例子就是先将变量x赋值为一个向量,然后求取其对数。

x <- c(1,2,3,4)
log(x)
## [1] 0.0000000 0.6931472 1.0986123 1.3862944

如果我们想从变量x中取出某一个元素的话,可以使用方括号加索引号,下面取出第二个元素:

x[2]
x[2:4]
x[-4]
x[x>2]

数组

数组(Array)是一种多维的向量,建立数组的方法如下:

a <- array(1:12,dim=c(3,4))
print(a)
##      [,1] [,2] [,3] [,4]
## [1,]    1    4    7   10
## [2,]    2    5    8   11
## [3,]    3    6    9   12
a[2,2]
a[2,]

数据框

数据框(Data frame)是一种类似Excel表格的数据结构,其中每列的数据类型可以不同,但数据长度必需一致。数据框非常适合用来进行数据分析,它的每一列可以代表数据的每个变量或属性,每一行可以代表一个样本。下面我们来构建一个有三个属性、五个样本的数据框。

city  <- c('beijing','shanghai','chengdu','shanghai','beijing')
age <- c(23,43,51,32,60)
gender <- c('F','M','F','F','M')
people <- data.frame(city,age,gender)
print(people)
##       city age gender
## 1  beijing  23      F
## 2 shanghai  43      M
## 3  chengdu  51      F
## 4 shanghai  32      F
## 5  beijing  60      M

数据框

和数组操作一样,我们可以用方括号来提取数据框中的元素。另一种方法是用$ 符号来提取某一列。例如提取age变量和gender变量。

people$age
## [1] 23 43 51 32 60
people$gender
## [1] F M F F M
## Levels: F M
people$age>30
people$city[people$age>30]

列表

列表(List)是最为灵活的数据结构,它的不同元素可以是不同类型,也可以是不同的长度。还是用age、city、gender三个向量来构建列表。

peoplelist <- list(age=age,city=city,gender=gender)
print(peoplelist)
## $age
## [1] 23 43 51 32 60
## 
## $city
## [1] "beijing"  "shanghai" "chengdu"  "shanghai" "beijing" 
## 
## $gender
## [1] "F" "M" "F" "F" "M"
people.list$array <- a
people.list$dataframe <- people

对象和类

有一个非常有用的函数str()能用以了解一个对象的底细。

str(people)
## 'data.frame':    5 obs. of  3 variables:
##  $ city  : Factor w/ 3 levels "beijing","chengdu",..: 1 3 2 3 1
##  $ age   : num  23 43 51 32 60
##  $ gender: Factor w/ 2 levels "F","M": 1 2 1 1 2

模型与公式

对统计学家来讲,模型是用以描述数据的简洁方式。很多时候模型以公式的形式展现,用以预测或解释。

y ~ x1 + x2 + x3 ... + xn

下面我们用一个具体的线性回归例子来看一下,使用的数据集是R内置的数据car。R语言中用于回归的函数是lm,回归后的结果存入变量model中。

model <- lm(formula=dist ~ speed, data=cars)

summary函数提供了关于回归结果更为丰富的信息,包括了各系数及其对应的P值,残差标准误和决定系数等。

summary(model)
## 
## Call:
## lm(formula = dist ~ speed, data = cars)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -29.069  -9.525  -2.272   9.215  43.201 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -17.5791     6.7584  -2.601   0.0123 *  
## speed         3.9324     0.4155   9.464 1.49e-12 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 15.38 on 48 degrees of freedom
## Multiple R-squared:  0.6511, Adjusted R-squared:  0.6438 
## F-statistic: 89.57 on 1 and 48 DF,  p-value: 1.49e-12

深入学习之数据对象

基本对象:向量

  • 单个数值(标量)是向量的一种特例
  • 向量的元素必须属于某种模式(mode),可以整型(integer)、数值型(numeric)、字符型(character)、逻辑型(logical)、复数型(complex)
  • 循环补齐(recycle):在一定情况下自动延长向量
  • 筛选:提取向量子集
  • 向量化:对向量的每一个元素应用函数
  • 使用seq()创建向量
  • 使用rep()重复向量常数
vector1 <- seq(2,10,2)
vector1 <- 1:10 + 2
vector2 <- 1:(10 + 2)

向量的计算

去掉最大值和最小值后的向量的算术均值

vector <- rnorm(10)
vec_max <- max(vector)
vec_min <- min(vector)
vector_trimmed <- vector[vector<vec_max & vector>vec_min]
vec_mean <- sum(vector_trimmed)/length(vector_trimmed)

复合对象

复合对象是建立在向量基础上的数据结构,这些复合对象是为了满足数据分析的需要而建立的。下面来介绍三种数据结构:矩阵、数据框和列表。

vector <- 1:12
my_matrix <- matrix(vector,nrow=3,ncol=4,byrow=F) 
dim(my_matrix)
dim(vector) <- c(4,3)
print(vector)

矩阵

vector1 <- vector2 <- vector3 <- rnorm(3)
my_matrix <- cbind(vector1,vector2,vector3)
ifelse(my_matrix>0,1,0)
##      vector1 vector2 vector3
## [1,]       1       1       1
## [2,]       0       0       0
## [3,]       1       1       1

求解线性方程组

A <- matrix(c(3,1,5,2),2,2)
b <- matrix(c(4,1),ncol=1)
x <- solve(A,b)

算术运算小结

  • x + y 加法
  • x - y 减法
  • x * y 乘法
  • x / y 除法
  • x ^ y 乘幂
  • x %% y 模运算
  • x %/% y 整数除法

逻辑运算小结

  • x == y 判断是否相等
  • x <= y 判断是否小于等于
  • x >= y 判断是否大于等于
  • x & y 向量的逻辑“与”运算(x、y以及运算结果都是向量)
  • x | y 向量的逻辑“或”运算(x、y以及运算结果都是向量)
  • !x 逻辑非
  • 逻辑值TRUEFALSE可以缩写为TF(两者都必须是大写)。而在算术表达式它们会转换为1和0

数据框

构建一个有两个属性、五个样本的数据框。

city <- c('A','B','C','D')
temp = c(27,29,23,14)
data <- data.frame(city,temp)

提取数据框中的元素

data[ ,1]
data[, 'city']
data$city

数据框

因子转换问题,如果不需要自动转换的话,你可以按如下方式手工进行参数设定。

data <- data.frame(city,temp,stringsAsFactors=F)

数据框将不同向量组合一起更方便操作,我们仍来尝试找出高于平均温度的城市。

ave <- mean(data$temp)
data[data$temp>ave, ]
##   city temp
## 1    A   27
## 2    B   29

数据框

对于一个陌生的数据框,最快速的熟悉方法就是使用下面几个函数。

data <- data.frame(city,temp)
summary(data)
dim(data)
head(data)
str(data)

summary函数负责对每列进行统计,dim得到维度,head得到前六行数据,而str则返回整个数据的结构。

数据框

数据框排序排序,order函数

order(data$temp)
data[order(data$temp),]
data[order(data$temp,decreasing=T),][1:2, ]

列表

列表(List)是最为灵活的数据结构,它的不同元素可以是不同类型,也可以是不同的长度

data_list = list(temp=temp,city=city)
print(data_list)
## $temp
## [1] 27 29 23 14
## 
## $city
## [1] "A" "B" "C" "D"
data_list$mat <- my_mat
data_list$data <- data

列表

列表也能使用数字作为索引提取元素,但需要用两个方括号。例如提取最后一个data元素。

names(data_list)
data_list$data
length(data_list)
data_list[[4]]

缺失值与空值

真实的数据分析工作中会经常遇到数据缺失情况,缺失的数据在R中一般表示为NA。当一个数据中包含了NA时,很多函数的行为会不一样,甚至会产生错误。

temp <- c(27, 29, 23, 14,NA)
mean(temp)
mean(temp,na.rm=T)
is.na(temp)

缺失值与空值

缺失值的意义是应该有数据而没有,起到一个占位符的作用。空值的意义则是完成没有,空值的表示是NULL。下面的例子中temp仍然只有四个元素。

temp <- c(27, 29, 23, 14,NULL)

NULL有时候可以用来方便的删除复杂对象中的一个元素,例如删除前面data_list中的data元素。

data_list$data <- NULL

函数和控制语句

函数的构成

和数学中的函数概念类似,函数由三部分构成,即输入、运算、输出。

exp(c(1,2,3,4))
## [1]  2.718282  7.389056 20.085537 54.598150

自定义函数

一个求圆面积的函数

myfunc <- function(r) {
  area <- pi*r^2
  return(area)
  }
print(myfunc(4))
## [1] 50.26548

函数在调用时会新建一个特殊的子环境,用以处理函数中涉及到的变量,例如上面函数中的area变量,这种变量称为局部变量,因为不会在全局环境中出现而影响其它函数,使用起来非常安全。但函数内部可以调用全局变量,例如上面的pi。

条件判断

通常R代码的执行是按行顺序执行的,但为了执行复杂点的任务,需要根据某些条件判断来执行某些分支代码

num <- 5
if (num %% 2 != 0) {
  cat(num,'is odd')
}
## 5 is odd

条件判断

if只是单一判断是否执行某条代码,若需要多分支判断,可增加else语句,例如增加奇数和偶数的屏幕输出。

num <- 4
if (num %% 2 != 0) {
  cat(num, 'is odd')
} else {
  cat(num, 'is even')
}
## 4 is even

条件判断

对于超过两个分支的条件判断,我们可以使用多重嵌套的if-else语句。例如计算某个数字和3相除的余数。

num <- 10
if (num %% 3 == 1)  {
  cat('mode is',1)
} else if (num %% 3 == 2) {
  cat('mode is',2)
} else {
  cat('mode is',0)
}
## mode is 1

二元判断函数

ifelse可用于向量化计算,例如判断多个数字是奇数还是偶数。

num <- 1:6
ifelse(num%%2==0, yes='even',no='odd')
## [1] "odd"  "even" "odd"  "even" "odd"  "even"

ifelse的嵌套

num <- sample(20:70,20,replace=T)
res <- ifelse(num>50,'老年',ifelse(num<30,'青年', '中年'))

循环

循环语句可以重复运行某一段代码。根据终止的条件,可以将循环分为for循环和while循环。

for循环的终止条件是循环的次数,例如我们计算1到100所有奇数的和。

x <- 0
for (i in 1:100) {
  if (i %% 2 != 0) {
    x <- x + i
  }
}

实际应用中,计算奇数之和只需要一条代码即可。

sum(seq(1,100,by=2))

循环

while循环的终止条件是达到某一个标准,还是计算上面同样的例子。

x <- 0
i <- 1
while (i < 100) {
  if (i %% 2 != 0) {
    x <- x + i
  }
  i <- i + 1
}

循环

除了for、while循环之外,R语言中还可以使用repeat来进行无限次的循环操作。仍是计算100以内的奇数之和。

x <- 0
i <- 1
repeat  {
  if (i %% 2 != 0) {
    x <- x + i
  }
  i <- i + 1
  if (i > 100) break
}

循环

循环中另外一个常见的命令是next,也就是跳过循环中next后面的代码,而重新开始一次循环。

x <- 0
i <- 0
repeat  {
  i <- i + 1
  if (i > 100) break
  if (i %% 2 == 0) next
  x <- x + i
}

函数

编写自定义函数是非常容易的,下例是将前面的计算fibonaci数字的代码段转为一个函数。

fibonaci <- function(n) {
  i <- 2
  x <- 1:2
  while (x[i] < n) {
    x[i+1] <- x[i-1] + x[i]
    i <- i + 1
  }
  x <- x[-i]
  return(x)
}
SeqFi <- fibonaci(100)