《R语言与商业智能》读书笔记


学习《R语言与商业智能》 ,为了加深记忆,边读边做笔记。如有侵权,立即删除。

第 1 章 R简介

R是用于统计分析、统计绘图的语言和操作环境,是属于GNU系统的一个自由、免费、源代码开放的软件,也是一个用于统计计算和统计制图的优秀工具。

R的功能

R是一套完整的数据处理、计算和制图软件系统。其功能包括:数据存储和处理系统、数组运算工具(在向量、矩阵运算方面的功能尤其强大)、完整连贯的统计分析工具、优秀的统计制图功能、简便而强大的编程语言、可操纵数据的输入和输出,可实现分支、循环、用户可自定义功能。

与其说R是一种统计软件,还不如说R是一种数学计算的环境,因为R并不是仅仅提供若干统计程序,使用者只需指定数据来源和若干参数便可进行统计分析。R的思想是:它可以提供一些集成的统计工具,但更大量的是它提供各种数学计算、统计计算的函数,从而使使用者能灵活机动地进行数据分析,甚至创造出符合需要的新的统计计算方法。

R语言的语法表面上类似C,但在语义上是函数设计语言(functional programming language)的变种,并且和Lisp以及APL有很强的兼容性。特别的是,它允许在“语言上计算”(computing on the language)。这使得它可以把表达式作为函数的输入参数,而这种做法对统计模拟和绘图非常有用。

CRAN 和 Bioconductor

CRAN为 Comprehensive R Archive Network(R综合典藏网)的简称。它除了收藏了R可执行文件、源代码和说明文件,也收录了用户撰写的各种软件包。

R的缺点

  1. R是一种解释性语言,和编译语言相比,速度显得略慢一点,但是随着硬件和R自身的发展,这个问题已经慢慢消失了。
  2. R所有的计算都是在内存中进行的。
  3. 由于R语言的自由,各种包的编写者来自不同的领域,所以在一定程度上是比较混乱的,没有统一的命名格式,参数格式不一,源代码和文档质量良莠不齐。

R的使用

第一次使用R

在R中可以使用“=”,也可是使用“<-”来赋值,在实际使用中,这两种方法几乎没有区别。但是,一般在赋值的时候使用箭头,在传递参数的时候使用等号(必须使用等号,虽然有的时候用箭头也可以运行,但是很危险)。

1
2
3
4
5
6
> x<-1:10
> x
[1] 1 2 3 4 5 6 7 8 9 10
> y=1:10
> y
[1] 1 2 3 4 5 6 7 8 9 10

不推荐使用等号赋值。在R中使用井号“#”来注释。

获取帮助

1
2
3
4
5
6
7
8
#查看函数的帮助
help(rnorm) #等价于?rnorm
#模糊查询
help.search("rnor")#等价于??rnor
#查看一个函数的例子的运行结果
example("rnorm")
#列出包当中的小短文
vignette()

工作空间和工作目录

R是在内存中运行的,所使用的数据和函数等都在内存中,这被称为之为工作空间。可以使用ls()来列出当前工作空间中的多有对象,使用rm()来删除工作空间中的某一个对象,特别地,可以使用rm(list=ls(all.names=T))来删除所有的对象,包括其中隐藏的对象。

另外一个概念是工作目录,工作目录是一个文件夹的路径,这个路径表示的是当前在哪一个文件夹下工作。在存取文件时,如果不指定路径的话,就会默认为这个文件夹。在R中,可以使用getwd(即get work directory)函数来获得当前目录,如果要改变当前工作目录,可以使用setwd函数来设置。

包的安装和使用

在R中使用命令来安装包

1
2
3
4
5
6
# 在R中使用命令来安装包
install.packages("安装的包名",dependencies=TRUE)
# 加载一个包
library("包名")
# 查看一个包的使用说明
library(help="包名")

一个包在安装完成后需要先加载才能使用。

第 2 章 数据结构

数据结构

向量

向量是用来储存一维数据的,其中的数据必须具有相同的数据类型,比如都是整数或者都是字符。可以用c()来创建向量。

1
2
3
> v.number<-c(1,2,3,4,5,6)
> v.char<-c("Jane","Justin","Tom")
> v.bool<-c(TRUE,FALSE,FALSE)

在R中除了0、NULL和NA之外的其他值都是真,其中NULL和NA是无法辨认真假的,可以通过以下例子来理解:

1
2
3
4
5
6
7
> if(-1) print("true")    #-1为真
[1] "true"
> if(0) print("false") #无输出
> if(NA) print("false") #报错,无法比较
Error in if (NA) print("false") : missing value where TRUE/FALSE needed
> if(NULL) print("false") #报错,无法比较
Error in if (NULL) print("false") : argument is of length zero

在R中,如果在一个向量中有两种不同的数据类型,那么数据之间会进行转化,转化的顺序为由低级向高级转换,数据类型的的高低级顺序为”NULL<raw<integer<double<complex<character<list<expression”。

1
2
3
4
5
6
7
8
9
> x<-c(1:10,"Jane")
> x
[1] "1" "2" "3" "4" "5" "6" "7" "8" "9" "10"
[11] "Jane"
> class(x) #返回变量的数据类型
[1] "character"
> y<-c(1:10)
> class(y)
[1] "integer"

可以通过方括号来访问向量中的元素,注意,在R中,向量的下标是从1开始的,而不是0。

1
2
3
4
5
6
7
8
9
10
11
12
> x<-c(1:10)
> x[0] #x[0]返回的是一个和x类型相同的空对象
integer(0)
>
> x[1] #取出第1个元素
[1] 1
> x[2:4] #取出第2到第4个元素
[1] 2 3 4
> x[-1] #取出除了第1个以外的元素
[1] 2 3 4 5 6 7 8 9 10
> x[11] #返回NA值,注意和x[0]的不同
[1] NA

上面出现了x[-1],在R中,这种写法表示的意思是:除了第1个元素之外的其他元素。

注意:在给变量命名的时候,需要符合一定的规则,必须是以字母或者“.”开头,并且“.”开头的名字后的第一个字符只能是下划线(“_”)或者字母。想要规范R语言命名和编程规范,推荐Google的R语言编程风格指南(Google’s R Style Guide)。

矩阵

矩阵是一个二维数组,和向量一样,在创建它的时候,也需要注意其数据应该具有相同的数据类型,可以使用函数matrix来创建,matrix的使用方法为:

1
matrix(data=NA,nrow=1,ncol=1,byrow=FALSE,dimnames=NULL)

data表示一个向量,也就是需要创建的矩阵中的元素。nrow表示行数,ncol表示列数。byrow是一个逻辑值,如果为TRUE,则会按照行来排列,在默认的情况下,是按照列排列的。R中是列优先而不是行优先,这对于使用单下标获取元素有影响。dimnames表示向量的行和列的名字,在默认的情况下是没有名字的。与向量类似,可以通过下标来取出元素,比如x[1,2]表示第一行第二列的元素,则x[,1]则表示所有行的第一列元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
> rowName<-paste("row",1:3,sep='') #创建行名
> colName<-paste("col",1:4,sep='') #创建列名
> (m1<-matrix(data=1:12,nrow=3,byrow=TRUE,dimnames=list(rowName,colName)))
col1 col2 col3 col4
row1 1 2 3 4
row2 5 6 7 8
row3 9 10 11 12
>
> (m2<-matrix(data=1:12,nrow=3,byrow=FALSE,dimnames = list(rowName,colName)))
col1 col2 col3 col4
row1 1 4 7 10
row2 2 5 8 11
row3 3 6 9 12
> m1[1,2]
[1] 2
> m1[1,2:4]
col2 col3 col4
2 3 4
> m1[,1]
row1 row2 row3
1 5 9
> m1[3] #等价于m1[3,1]
[1] 9

这里需要注意m1[3]的值,因为列优先,所以m1[3]和m1[3,1]是等价的。此外,上面使用了paste来构建行名和列名,关于paste函数的具体用法,在讲解字符串函数的时候会进行分析。

数组

数组可以看成是矩阵的一个扩展,矩阵的维度只能是2,而数组的维度则可以更高,仍然要注意,数组数据的类型也要相同。可以通过函数array来创建数组,array函数的一般使用方法为:

1
array(data = NA,dim = length(data),dimnames = NULL)

data表示一个向量,也就是我们想要用来构建数组的数据;dim表示数据的维度,也是一个向量,其默认值是数据的长度,也就是说默认建立1xn的向量;dimnames用来指定各个维度上的名字。与向量和矩阵类似,仍然通过下标来获取元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
> dim1Name<-paste("A",1:3,sep='')
> dim2Name<-paste("B",1:4,sep='')
> dim3Name<-paste("C",1:2,sep='')
> (a<-array(1:24,dim=c(3,4,2),dimnames=list(dim1Name,dim2Name,dim3Name)))
, , C1

B1 B2 B3 B4
A1 1 4 7 10
A2 2 5 8 11
A3 3 6 9 12

, , C2

B1 B2 B3 B4
A1 13 16 19 22
A2 14 17 20 23
A3 15 18 21 24

> a[1,1,1]
[1] 1
> a[1,2,]
C1 C2
4 16
> a[1,,]
C1 C2
B1 1 13
B2 4 16
B3 7 19
B4 10 22
> a[,1,]
C1 C2
A1 1 13
A2 2 14
A3 3 15

因子

变量有连续性变量和非连续性变量之分,而非连续性变量又有有序和无序之分。对于连续性变量,使用数字来表示是有意义的,可以对其进行代数计算。而对于非连续型变量,它们有的有次序之分,有的无次序之分,变量只是用来标识不同的事件。在R中,对于连续性变量,使用integer(整数)或者numeric(实数)等类型的数据来表示;而对于非连续性变量,则专门使用一种称之为因子的类型来描述这种变量。在R中创建和改变因子会用到两个函数:factor和levels。

1
2
factor(x = character(), levels,labels = levels, exclude = NA,ordered = is.ordered(x),nmax = NA)
levels(x)

x 表示需要创建为因子的数据,是一个向量;levels表示所创建的因子数据的水平,如果不指定的话,就是x中不重复的所有值;labels用来标识这一水平的名称,与水平一一对应,labels是为了更加方便用户识别;exclude表示有哪些水平是不需要的;ordered是一个逻辑值,如果是TRUE,则表示有序因子,是FALSE则表示无序因子;nmax表示的是水平个数的上限。

列表

list是一个强大的容器,可以在其中放入各种类型的的变量,比如数字、字符、向量、矩阵、数组以及数据框,甚至是列表本身。

1
list(x1,x2,x3,...)

列表的参数就是要放入列表的元素。访问列表有两种方式,既可以通过下标来访问列表,也可以使用符号$来访问。使用[ ]时,必须使用精确值来匹配;而使用$时,则可以使用模糊匹配。对于[[ ]]的使用,可以这样理解:对于一个列表,用下标[ ]取出来后的元素仍然是一个列表,所以需要把它解析成向量的时候,需要再加一个[ ]。

数据框

数据框并不要求存储在其中的所有的数据类型都一样,但对于每一列的数据类型还是要求一样的。可以使用data.frame()创建数据框。

1
data.frame(...,row.names = NULL, check.rows = FALSE, check.names = TRUE, stringsAsFactors = default.stringsAsFactors())

“…”表示各个列的数据集;row.names表示行名;check.rows是逻辑值,表示是不是检查行的长度和名字;check.names也是逻辑值,用来检查名字是不是合法;stringAsFactors是一个比较重要的参数,也是一个逻辑值,表示是不是把数据集中的字符串转化为因子类型。需要特别注意的是,如果不考虑这个参数,有时会把一些不想当作因子的函数当做因子来处理。

数据的导入与导出

从键盘输入

1
2
3
4
5
6
m1 <- matrix(0)
m2 <- matrix(0)
edit(m1)
fix(m2)
x<-scan()
y <- scan(what=list(name="",age=0)) # what指出输入的数据格式,可以通过给变量赋值的方式指明数据的格式。

使用edit编辑后的对象仍然是原来的,所做的修改没有保存,而使用fix修改过的对象则保留了修改。scan是一个比较底层的读取数据函数,可以从屏幕和文件中读取数据,按回车键表示输入结束。

从纯文本中读取数据

1
(x<-read.table(file = "D:/data.txt",head = TRUE,sep = ",",colClasses = c("character","factor","numeric","numeric")))

总结和补充

补充

class函数可以用来查看R中对象的类型。

1
2
x <- 1:10
class(x)

在创建一个向量的时候,难免出现重复,而处理这种情况的比较好的方案之一就是使用rep()函数。

1
rep(x,times,each,length.out,...)

x 表示的是需要重复的那个向量;each 表示每个元素重复的次数,如果设置为空或者设置为非法参数,则当作是1来处理;times 表示经过each处理以后的新的向量中每个元素重复的次数。each 和times 应该是和x等长度的向量,但是,如果比x的长度短,就会重复使用该向量。

使用gl函数创建因子型。

1
2
# 创建一个3水平的每个水平重复2次的因子序列 
gl(n=3,k=2,labels=c("R","Python","Lisp"))

n 表示的是创建的变量的水平,k 表示的是每个水平重复的次数,labels 表示的是水平对应的标签。

cbind 函数和 rbind 函数是用来合并数据集的,cbind 表示的是按列,而 rbind 表示的是按行合并。

1
2
cbind(..., deparse.level=1)
rbind(..., deparse.level=1)

“…” 表示需要合并的各个数据集,deparse.level 是一个整数,可以取 1、2、3,用来控制标签的建立,0 表示没有标签,1 表示如果有标签,就使用标签;2 表示没有标签时,强制使用参数的名字作为标签。这里的合并不是按照某一个关键字合并,如果要按照关键字合并,可以参考R中的merge。

1
2
3
4
rbind(1:4, c=2,"aa"=10,a,deparse.level = 0)  # 中间两行有标签
rbind(1:4, c=2,"aa"=10,a,deparse.level = 1) # 后三行有标签
rbind(1:4, c=2,"aa"=10,a,deparse.level = 2) # 全部都有标签
cbind(1:4, c=2,"aa"=10,a,deparse.level = 2) # 列合并

head 和 tail这两个函数可以只查看数据集的前几行和后几行。

1
2
head(iris) # 查看前6行
tail(iris , n=3) # 查看后3行

head 和 tail 的参数只有两个,第一个是要查看的数据集,第二个是要查看的行数。

第3章 数据清理和转换

数据清理

缺失值的处理

which() 函数的用法:

1
2
which(x, arr.ind = FALSE, ...)
SSEC <- na.omit(SSEC) # 删除空缺的数据

which 用来寻找逻辑值为真的值所在的位置。x 表示的是一个逻辑向量或者数组;arr.ind 是一个逻辑值,如果为真,会得出在数据中的位置,否则会得到储存的索引。

类型转化

as.Date() 函数的使用

1
as.Date(x, format="", tz="")

参考文档:
Rstudio install.packages失败解决方式