数据分析的首要任务是数据组织。数据对象是 R 存储管理数据的基本方式。每个数据对象都有一个对象名,它是创建、访问和管理对象的唯一标识。对象名通常由若干区分大小写的英文字母组成。
R 数据对象可有两种不同角度的类型划分:第一种,从存储角度划分类型;第二种,从结构角度划分类型。
数据对象是 R 组织数据的基本方式。由于不同类型的数据在计算机中所需的存储字节不同,可将 R 数据对象划分为数值型、字符型、逻辑型等主要存储类型。了解 R 数据对象的存储类型,能够保证数据处理的一致性,有效避免后续 R 程序编写过程中的某些语法错误。
(1)数值型
数值型(Numeric)是计算机存储诸如人口数、空气中 PM2.5 浓度等数值型数据的类型总称。数值型可进一步细分为整数型(Integer)和实数型(Double)。
a<-10
b<-10.2
str(a)
## num 10
str(b)
## num 10.2
is.integer(a)
## [1] FALSE
is.double(a)
## [1] TRUE
(2)字符型
字符型(Character)是计算机存储诸如姓名、籍贯等字符形式数据的类型。字符型常量的具体形式如”ZhangSan”、“BeiJing”等,是由英文双引号括起来的一个字符序列,简称字符串。
name<-"金融"
print(name)
## [1] "金融"
(3)逻辑型
逻辑型(Logical)是计算机存储诸如是否已婚、是否通过某个考试等是非判断形式数据的类型。逻辑型数据只有真(是)、假(否)两个常量取值,具体形式为大写的英文单词 TRUE和 FALSE。
is.logical(name)
## [1] FALSE
is.character(name)
## [1] TRUE
从数据组织结构角度划分 R 对象
数据对象是 R 组织数据的基本方式。由于数据分析实践中有不同的数据组织结构,所以 R 数据对象可划分为向量、矩阵、数组、数据框、列表等多种结构类型。了解 R 数据对象的结构类型,是根据数据实际情况,选择恰当数据组织方式的基础。
(1)向量(Vector)
向量是 R 数据组织的基本单位。从统计角度看,一个向量对应一个变量,存储着多个具有相同存储类型的变量值。若无明确说明,向量均为列向量。
# 使用 c() 函数创建一个数值向量
x <- c(1, 2, 3, 4, 5)
print(x)
## [1] 1 2 3 4 5
# 使用 seq() 函数创建一个等差数列
y <- seq(0, 1, by = 0.2)
print(y)
## [1] 0.0 0.2 0.4 0.6 0.8 1.0
# 创建一个长度为 10 的零向量
z <- numeric(10)
print(z)
## [1] 0 0 0 0 0 0 0 0 0 0
(2)矩阵(Matrix)
矩阵是一个二维表格形式,用于组织多个具有相同存储类型的变量。矩阵的列通常为变量,行为观测。
# 创建一个 2 行 3 列的矩阵
m <- matrix(c(1, 2, 3, 4, 5, 6), nrow = 2, ncol = 3)
print(m)
## [,1] [,2] [,3]
## [1,] 1 3 5
## [2,] 2 4 6
(3)数组(Array)
数组是多张二维表的集合,一般用于组织统计中的面板数据等。
# 创建一个带有维度名称的数组
x <- array(c(1, 2, 3, 4, 5, 6), dim = c(2, 2), dimnames = list(c("Row1", "Row2"), c("Col1", "Col2")))
print(x)
## Col1 Col2
## Row1 1 3
## Row2 2 4
da(4)数据框(Data Frame)
数据框也是一张二维表格,与矩阵有类似之处,但用于组织存储类型不同的多个变量。其中,数据框的列通常为变量,行为观测。
# 创建一个包含姓名、年龄和成绩的数据框
name <- c("Alice", "Bob", "Charlie")
age <- c(25, 30, 28)
score <- c(90, 85, 92)
df <- data.frame(Name = name, Age = age, Score = score)
print(df)
## Name Age Score
## 1 Alice 25 90
## 2 Bob 30 85
## 3 Charlie 28 92
(5)列表(List)
多个向量、矩阵、数组、数据框、列表的集合即列表。多用于相关统计分析结果的”打包”集成。
# 创建一个包含不同类型对象的列表
my_list <- list(name = "Alice",
age = 25,
scores = c(90, 85, 92),
matrix = matrix(1:9, nrow = 3),
data_frame = data.frame(A = 1:3, B = c("x", "y", "z")),
my_function = function(x) { return(x^2) }
)
print(my_list)
## $name
## [1] "Alice"
##
## $age
## [1] 25
##
## $scores
## [1] 90 85 92
##
## $matrix
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
##
## $data_frame
## A B
## 1 1 x
## 2 2 y
## 3 3 z
##
## $my_function
## function(x) { return(x^2) }
数据分析的首要任务是数据的组织管理,且 R 的对象是用于数据组织的,所以应首先创建 R 对象,然后才能对其进行相关的管理等。
1.创建R 对象
创建 R对象是通过赋值语句实现的。基本书写格式:
对象名<- R 常量或 R函数
式中,“<-”称为 R 的赋值操作符,功能是将其右侧的计算结果赋值到左侧对象所在的内存单元中,也称给 R 对象赋值。一方面,赋值操作符右侧的具体书写形式会因 R 对象存储类型和组织结构类型的不同而不同;另一方面,赋值操作符右侧不同的书写形式也决定了其左侧对象的类型。每个对象都有一个对象名。
#在 R 中,赋值符号使用 "<-" 或 "=" 进行赋值操作。这两个符号都可以用于将值赋给变量。
xy = 12
yt = 2
ans = xy/yt
print(ans)
## [1] 6
2.访问R对象
访问数据对象,即浏览 R 对象的具体取值(也称对象值)。基本书写格式:
对象名
或
print(对象名)
于是,指定 R 对象的对象值将按行顺序显示在 R 的控制台窗口中。
x1 <- 1
x1
## [1] 1
print(x1)
## [1] 1
3.查看 R 对象的结构
查看 R 对象的结构,即查看 R 对象的存储类型以及与结构相关的信息。基本书写格式:
str(对象名)
于是,指定对象的相关结果信息将显示在 R 的控制台窗口中。
str(x1)
## num 1
4.管理R对象
管理 R 对象即浏览当前工作空间中包含哪些对象,可删除不再有用的对象等。基本书写格式:
1s0
于是,当前工作空间中的对象名列表将显示在 R 的控制台窗口中。
rmm(对象名或对象名列表)
对象名列表中包含多个对象名,各个对象之间应用英文逗号分隔。
remove(对象名)
删除当前工作空间中的指定对象。
ls()
## [1] "a" "age" "ans" "b" "df" "m" "my_list"
## [8] "name" "score" "x" "x1" "xy" "y" "yt"
## [15] "z"
rm(age)
remove(x)
可通过 is 函数判断对象是否为向量,基本书写格式:
is.vector(对象名)
如果指定对象为向量,则函数返回结果为逻辑型常量 TRUE,否则为逻辑型常量FALSE。
R 向量对应一个变量。向量中元素的存储类型可以是数值型、字符串型或逻辑型,对应的向量依次称为数值型向量、字符串型向量或逻辑型向量。
1.最简单的 R 向量
在 R 的控制台窗口中依次输入以下 R 语句,观察执行结果。其中,“#”号后面的内容均为程序说明信息,是对程序的注释,不会被执行。
#创建整数形式的数值型向量
V1 <- 100
V2 <- 123.5
V3 <- "abcD"
print(V3)
## [1] "abcD"
(V4 <- TRUE)
## [1] TRUE
is.vector(V1)
## [1] TRUE
is.logical(V4)
## [1] TRUE
summary(cars)
## speed dist
## Min. : 4.0 Min. : 2.00
## 1st Qu.:12.0 1st Qu.: 26.00
## Median :15.0 Median : 36.00
## Mean :15.4 Mean : 42.98
## 3rd Qu.:19.0 3rd Qu.: 56.00
## Max. :25.0 Max. :120.00
说明:
(1)若将赋值语句放入圆括号中,则表示创建对象,并直接显示对象值。
2.利用 R向量组织变量
这里,以第 1章的 2016 年北京市空气质量监测数据为例,讲解如何用R 向量组织变量。
案例中有监测点名称(SiteName)、监测点类型(SiteTypes)两个变量,现用两个名为SiteName 和 SiteTypes 的向量对应监测点名称和监测点类型两个变量。代码和执行结果如下。
##创建向量
SiteName<-c("东四","天坛","官园","万寿西宫","奥体中心","农展馆","万柳","北部新区","植物园","丰台花园",
"云岗","古城","房山","大兴","亦庄","通州","顺义","昌平","门头沟","平谷","怀柔","密云","延庆","定陵",
"八达岭","密云水库","东高村","永乐店","榆垡","琉璃河","前门","永定门内","西直门北","南三环","东四环")
SiteTypes<-c(rep("城区环境评价点",12),rep("郊区环境评价点",11),rep("对照点及区域点",7),rep("交通污染监控点",5))
length(SiteName)
## [1] 35
length(SiteTypes)
## [1] 35
说明:
(2)各监测点的类型不尽相同。例如,前 12 个监测点均为城区环境评价点,可利用 rep函数简化程序书写。rep(“城区环境评价点”,12)表示重复生成 12 个”城区环境评价点”,rep(“郊区环境评价点”,11)表示重复生成11个”郊区环境评价点”。
3.访问 R向量中的元素
可通过以下三种方式访问 R 向量中的元素
(1)访问指定位置上的元素,有三种基本书写格式:
向量名[位置常量]
向量名[位置常量 1:位置常量 2]
向量名[c(位置常量列表)]
例如:在 R的控制台窗口中依次输入以下 R 语句,观察执行结果
a<-vector(length=10) #创建包含10个元素的向量a
a #显示初始值
## [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
a[1] <- 1 #访问第1个元素,并赋值为1
a[2:4] <- c(2,3,4) #访问第2至第4个元素,并赋值为2,3,4
a
## [1] 1 2 3 4 0 0 0 0 0 0
b<-seq(from=5,to=9,by=1) #生成一个取值5至9的序列给向量b
a[c(5:9,10)]<-c(b,10) #访问第5至9以及第10个向量,赋值为5至10
a
## [1] 1 2 3 4 5 6 7 8 9 10
说明:
方括号和圆括号的使用场合不同,不要混淆。
“:”是R的特殊操作符号。2:4 表示从2 开始到4 结束,即结果为 2,3,4。
b<-seq(from=起始值,to=终止值,by=步长):利用 seq 函数生成一组序列值,元素的取值范围是从 from 指定的起始值开始,到 to 指定的终止值结束,各元素之间相差 by 指定的数值(步长)。
上述 c(b,10)的访问方式,可有效实现多个向量的合并。
(2)利用位置向量访问指定位置上的元素
基本书写格式:
向量名[位置向量名]
若向量 A 出现在向量 B 后用于说明元素位置的方括号[]内,则向量 A 为向量 B 的位置向量
例如:在 R的控制台窗口中依次输入以下 R语句,观察执行结果
b<-(2:4) #创建数值型位置向量b,依次取值为2,3,4
a[b] #访问a中位置向量b所指位置(即2,3,4)上的元素
## [1] 2 3 4
b<-c(TRUE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE) #创建逻辑型向量b
a[b] #访问a中位置向量b取值为TRUE位置(即1,4)上的元素
## [1] 1 4
说明:
逻辑型向量 b 将作为一个位置向量,利用位置向量可以访问指定位置上的元素
(3)访问指定位置之外的元素
有四种基本书写格式:
向量名[-位置常量]
向量名[-(位置常量 1:位置常量 2)]
向量名[-c(位置常量列表)]
向量名[-位置向量名]
例如:在 R的控制台窗口中依次输入以下 R 语句,观察执行结果
a[-1] #访问除第1个元素以外的元素
## [1] 2 3 4 5 6 7 8 9 10
a[-(2:4)] #访问除第2至第4个元素以外的元素
## [1] 1 5 6 7 8 9 10
a[-c(5:9,10)] #访问除第5至第9以及第10个元素以外的元素
## [1] 1 2 3 4
b<-(2:4)
a[-b] #访问除位置向量b以外的元素
## [1] 1 5 6 7 8 9 10
ls() #显示当前工作空间中的对象列表
## [1] "a" "ans" "b" "df" "m" "my_list"
## [7] "name" "score" "SiteName" "SiteTypes" "V1" "V2"
## [13] "V3" "V4" "x1" "xy" "y" "yt"
## [19] "z"
rm(a,b) #删除当前工作空间中的对象a和对象b
说明:
负号”-“不仅表示算术运算中的减法,还可用于元素位置的指定,是 R 的一大特色。对逻辑型位置向量不能采用负号”-“的形式。
元素位置指定方式具有灵活性和多样性,是 R 特色的集中体现,也是 R 的初学者需要着重掌握的。
4.R的特殊向量:因子
因子是一种特殊形式的向量。通常意义的向量对应数值型变量,而因子则对应着分类型变量(包括类别型变量或顺序型变量)。
例如,可用”1”“2”“3”等分别表示籍贯,“籍贯”变量为类别型变量;考试成绩从高分到低分依次记为”A”“B”“C”“D”“E”“考试成绩”变量为顺序型变量。
因某些统计方法仅适用于数值型变量但不适用于分类型变量,而另一些统计方法仅适用于分类型变量但不适用于数值型变量,所以,区分变量是数值型还是分类型是必要的。
以北京市空气质量监测数据为例,监测点名称(SiteName)、监测点类型(SiteTypes)两个变量均为类别型变量,向量 SiteName、SiteTypes 应为因子才是合理的。但前例中它们均以字符串型向量出现,应将这两个向量转成因子。
因子的存储类型为整数型的 1,2,3,..,k,称为因子水平值,表示类别型变量有 k 个类别或顺序型变量有k个水平。可利用 is 函数判断指定对象是否为因子,基本书写格式:
is.factor(对象名)
如果指定对象为因子,则函数返回结果为逻辑型常量 TRUE,否则为逻辑型常量 FALSE。向量转换为因子的核心处理是,指定向量中的各个类别或水平与因子的哪个因子水平值相对应。例如,“考试成绩”向量中的类别值”A”“B”“C”“D”“E”依次对应因子的1,2,3,4,5 水平值还是对应 5,4,3,2,1 水平值。
可利用 levels 函数显示因子水平值对应的类别值,基本书写格式:
levels(因子名)
levels 函数将按因子水平值的升序显示所对应的类别值。
可利用 as 函数将向量转换为因子,基本书写格式:
as.factor(向量名)
例如:在 R 的控制台窗口中依次输入以下 R 语,观察执行结果
(a<-c("Poor","Improved","Excellent","Poor")) #创建包含4个元素的字符型向量a
## [1] "Poor" "Improved" "Excellent" "Poor"
is.vector(a) #判断a是否为向量
## [1] TRUE
(b<-as.factor(a)) #将字符型向量a转换为因子b并显示b
## [1] Poor Improved Excellent Poor
## Levels: Excellent Improved Poor
is.factor(b) #判断b是否为因子
## [1] TRUE
levels(b) #按因子水平值升序显示所对应的类别值
## [1] "Excellent" "Improved" "Poor"
typeof(b) #显示因子b的存储类型名
## [1] "integer"
说明:
本例中向量 a 包含 4 个元素,但有 2 个相同元素,所以只有 3 个类别值,转换为因子b后有 3 个因子水平值。
默认情况下,向量 a 中的类别值按字母顺序升序依次对应因子水平值 1,2,3。
因子的存储类型为 integer 整型,但显示的是类别型变量的类别值或顺序型变量的水平值。
as.factor()函数在应用中存在一定局限性,主要体现在:
第一,因子水平值和类别值的对应关系按照类别值的字母升序对应,字母顺序小的应对应小的因子水平值,字母顺序大的对应大的因子水平值,实际应用中这种对应关系并不总是合理的:
第二,as.factor()函数得到的因子总是对应类别型变量,无法体现顺序型变量具有水平顺序性的特点。factor()函数可较好地克服这些局限性,基本书写格式:
factor(向量名,order-TURE/FALSE,levels=(类别值列表))
其中,参数 order 用于指定所得因子对应变量的类型,TURE 表示对应顺序型变量,FALSE表示对应类别型变量:levels 用于依顺序列出类别值,列在前面的类别值对应的因子水平值较小,列在后面的类别值对应的因子水平值较大。
例如:在R的控制台窗口中依次输入以下R 语句,观察执行结果
(a<-c("Poor","Improved","Excellent","Poor")) #创建字符型向量a
## [1] "Poor" "Improved" "Excellent" "Poor"
(b<-factor(a,order=FALSE,levels=c("Poor","Improved","Excellent"))) #指定类别值和水平值的对应关系
## [1] Poor Improved Excellent Poor
## Levels: Poor Improved Excellent
(b<-factor(a,order=TRUE, levels=c("Poor","Improved","Excellent")))
## [1] Poor Improved Excellent Poor
## Levels: Poor < Improved < Excellent
说明:
由于通过 levels 参数顺序列出了类别值,所以 Poor 的因子水平值为 1,Improved 的因子水平值为 2,Excellent 的因子水平值为 3。
order 参数取 FALSE 时,因子各水平值对应的类别值之间无大小顺序:取 TRUE 时各水平值对应的类别值间有大小之分。如 Poor <Improved < Excellent。
进一步,利用 factor 函数还可以重新设定因子水平值所对应的类别值,具体书写格式:
factor(向量名,levels=c(类别值列表),labels=c(类别值列表))
其中,参数 levels 为原类别值,labels 为新类别值,它们是一一对应的。
例如:在 R的控制台窗口中依次输入以下 R 语句,观察执行结果
(a<-c("Poor","Improved","Excellent","Poor"))
## [1] "Poor" "Improved" "Excellent" "Poor"
(b<-factor(a,levels=c("Poor","Improved","Excellent")))
## [1] Poor Improved Excellent Poor
## Levels: Poor Improved Excellent
(b<-factor(a,levels=c("Poor","Improved","Excellent"),labels=c("C","B","A")))
## [1] C B A C
## Levels: C B A
说明:
通过 levels 和 labels 的共同作用,原类别值”Poor”“Improved”“Excellent”依次替换为”C”“B”“A”,且”C”“B”“A”对应的因子水平值分别为 1,2.3。
矩阵用来组织具有相同存储类型的一组变量。矩阵中元素的存储类型可以是数值型、字符串型或逻辑型,对应的矩阵依次称为数值型矩阵、字符串型矩阵或逻辑型矩阵。
可通过 is 函数判断数据对象是否为矩阵,基本书写格式:
is.matrix(对象名)
如果指定对象为矩阵,则函数返回结果为逻辑型常量 TRUE,否则为逻辑型常量 FALSE。
可通过 dim函数获得矩阵的行数和列数,基本书写格式:
dim(矩阵名)
1.将多个向量合并成 R 矩阵
以北京市空气质量监测数据为例,前面生成了 SiteName 和 SiteTypes 两个字符型向量现将它们合并成35 行 2列的矩阵。代码和执行结果如下。
SiteName<-c("东四","天坛","官园","万寿西宫","奥体中心","农展馆","万柳","北部新区","植物园","丰台花园",
"云岗","古城","房山","大兴","亦庄","通州","顺义","昌平","门头沟","平谷","怀柔","密云","延庆","定陵",
"八达岭","密云水库","东高村","永乐店","榆垡","琉璃河","前门","永定门内","西直门北","南三环","东四环")
SiteTypes<-c(rep("城区环境评价点",12),rep("郊区环境评价点",11),rep("对照点及区域点",7),rep("交通污染监控点",5))
Site<-cbind(SiteName,SiteTypes)
is.matrix(Site)
## [1] TRUE
dim(Site)
## [1] 35 2
说明:
1.利用 cbind 函数将多个列向量合并成一个矩阵。基本书写格式:
cbind(向量名列表)
其中,向量名列表是由英文逗号分隔的多个向量名。cbind函数创建的矩阵,行数取决于向量所包含的元素个数,列数取决于列向量的个数。
2.各向量合并成矩阵的前提是均有相同的存储类型。
2.将向量转换成 R矩阵
矩阵可由单个向量派生而来。如果矩阵中的数据元素已存在于一个向量中,可利用matrix 函数将该向量按指定方式转换成矩阵。基本书写格式:
matrix(向量名,nrow=行数,ncol=列数,byrow=TRUE/FALSE)
其中,nrow 和 ncol分别指定矩阵的行数、列数。例如:matrix(nrow=2,ncol=3)表示创建一个 2 行 3 列的矩阵。这里省略了向量名,创建的矩阵各元素默认取值为缺失值 NA。byrow参数指定将向量元素按怎样的顺序放置到矩阵中,TRUE 表示按行排列放置,FALSE 表示按列排列放置。
例如:在R的控制台窗口中依次输入以下 R 语句,观察执行结果。
m<-(1:30) #生成一个名为data的数值型向量
m<-matrix(m,nrow=5,ncol=6,byrow=FALSE) #将向量按列排列放置到5行6列的矩阵中
m
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 1 6 11 16 21 26
## [2,] 2 7 12 17 22 27
## [3,] 3 8 13 18 23 28
## [4,] 4 9 14 19 24 29
## [5,] 5 10 15 20 25 30
3.访问 R 矩阵中的元素
可通过数据编辑窗口以表格形式浏览矩阵的全部内容,基本书写格式:
fix(矩阵名)或 view(矩阵名)
或者,如果安装使用了 Rstudio,可直接单击矩阵名浏览矩阵。
R 程序设计中可能需要仅访问 R 矩阵中的某些元素并对其进行必要的处理,可通过以
下方式实现。
(1)访问指定位置上的元素
有三种基本书写格式:
矩阵名[行位置常量,列位置常量]
矩阵名[行位置常量 1:行位置常量 2,列位置常量 1:列位置常量2]
矩阵名[c(行位置常量列表),c(列位置常量列表)]
矩阵是二维表格的形式,访问时应给出两个位置参数,且用英文逗号分隔。英文逗号前的整数为行位置,后的整数为列位置。
例如:在R的控制台窗口中依次输入以下 R 语句,观察执行结果。
m<-(1:30) #生成一个名为data的数值型向量
m<-matrix(m,nrow=5,ncol=6,byrow=FALSE) #将向量按列排列放置到5行6列的矩阵中
m
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 1 6 11 16 21 26
## [2,] 2 7 12 17 22 27
## [3,] 3 8 13 18 23 28
## [4,] 4 9 14 19 24 29
## [5,] 5 10 15 20 25 30
m[2,3]
## [1] 12
m[1:2,2:3]
## [,1] [,2]
## [1,] 6 11
## [2,] 7 12
m[1:2,c(1,3)]
## [,1] [,2]
## [1,] 1 11
## [2,] 2 12
(2)访问指定行上的所有元素
有四种基本书写格式:
矩阵名[行位置常量,]
矩阵名[行位置常量 1:行位置常量 2,]
矩阵名[c(行位置常量列表),]
矩阵名[行位置向量名,]
其中,省略英文逗号后面的列位置参数,表示访问指定行上的所有列。
(3)访问指定列上的所有元素
有四种基本书写格式:
矩阵名[,列位置常量]
矩阵名[,列位置常量 1:列位置常量 2]
矩阵名[,c(列位置常量列表)]
矩阵名[,列位置向量名]
其中,省略英文逗号前面的行位置参数,表示访问指定列上的所有行。例如:在R的控制台窗口中依次输入以下 R 语,观察执行结果
m[2,] #访问第2行上的所有元素
## [1] 2 7 12 17 22 27
m[c(1,3),] #访问第1,3行上的所有元素
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 1 6 11 16 21 26
## [2,] 3 8 13 18 23 28
a<-c(TRUE,FALSE,TRUE,FALSE,FALSE) #利用逻辑型位置向量访问第1,3行上的所有元素
m[a,]
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 1 6 11 16 21 26
## [2,] 3 8 13 18 23 28
m[,1:3] #访问第1至3列上的所有元素
## [,1] [,2] [,3]
## [1,] 1 6 11
## [2,] 2 7 12
## [3,] 3 8 13
## [4,] 4 9 14
## [5,] 5 10 15
a<-matrix(nrow=5,ncol=2) #创建一个5行2列的矩阵,初始值默认为缺失值NA
a
## [,1] [,2]
## [1,] NA NA
## [2,] NA NA
## [3,] NA NA
## [4,] NA NA
## [5,] NA NA
a[,1]=seq(from=1,to=10,by=2) #给矩阵第1列赋值
a[,2]=seq(from=10,to=1,by=-2) #给矩阵第2列赋值
a
## [,1] [,2]
## [1,] 1 10
## [2,] 3 8
## [3,] 5 6
## [4,] 7 4
## [5,] 9 2
说明:
矩阵元素的访问方式与向量元素的访问类似,只是需要分别指定两个位置参数
访问指定位置之外的元素,须在位置参数前添加负号”-”
总之,相对于向量,矩阵的数据组织形式更直观,更具整体性,更便于数据管理。
4.创建和访问 R 数组
数组以三维方式组织数据,是矩阵的扩展形式。可将数组视为由多张二维表格罗列而成的”长方体”。表格的行列数分别对应长方体的长和宽,表格的张数对应长方体的高。数组包含的元素可以是数值型、字符串型或逻辑型,对应的数组依次称为数值型数组、字符串型数组或逻辑型数组。
可通过 is 函数判断数据对象是否为数组,基本书写格式:
is.array(对象名)
如果指定对象为数组,则函数返回结果为逻辑型常量 TRUE,否则为逻辑型常量FALSE。
创建数组可通过 array 函数,基本书写格式:
array(向量名,c(n1,n2,n3),dimnames=list(维名称列表))
其中,数组中的数据已事先存储在指定的向量中:c(n1n2m3)指定数组中有 n3 张行数为 n1列数为 n2 的二维表;dimnames 用于指定各个维的名称,可以省略。
例如:在R的控制台窗口中依次输入以下 R 语句,观察执行结果。
a<-(1:60)
dim1<-c("R1","R2","R3","R4") #分别给三个维命名
dim2<-c("C1","C2","C3","C4","C5")
dim3<-c("T1","T2","T3")
a<-array(a,c(4,5,3),dimnames=list(dim1,dim2,dim3)) #数组a由3张行数为4列数为5的二维表组成
a #逐张显示各张二维表的内容
## , , T1
##
## C1 C2 C3 C4 C5
## R1 1 5 9 13 17
## R2 2 6 10 14 18
## R3 3 7 11 15 19
## R4 4 8 12 16 20
##
## , , T2
##
## C1 C2 C3 C4 C5
## R1 21 25 29 33 37
## R2 22 26 30 34 38
## R3 23 27 31 35 39
## R4 24 28 32 36 40
##
## , , T3
##
## C1 C2 C3 C4 C5
## R1 41 45 49 53 57
## R2 42 46 50 54 58
## R3 43 47 51 55 59
## R4 44 48 52 56 60
is.array(a) #判断a是否为数组
## [1] TRUE
a[1:3,c(1,3),] #显示数组中所有表格的第1至3行,第1,3列的数据内容
## , , T1
##
## C1 C3
## R1 1 9
## R2 2 10
## R3 3 11
##
## , , T2
##
## C1 C3
## R1 21 29
## R2 22 30
## R3 23 31
##
## , , T3
##
## C1 C3
## R1 41 49
## R2 42 50
## R3 43 51
说明:
数组显示以表格为单位,依次列出各表的数据内容
数组元素的访问方式与矩阵元素的访问类似,但要分别指定行号、列号、表号三个位置参数。
销售数据如下:
产品名称(Product):篮球, 足球, 网球, 排球
产品价格(Price):100, 50, 80, 30
销售数量(Quantity):20, 15, 10, 5
要求:
创建一个向量来存储产品名称。
创建一个矩阵来存储产品价格和销售数量,每一行对应一个产品的信息。
创建一个数据框来存储销售数据,将向量和矩阵中的数据合并为一个数据框。
打印出数据框的摘要信息,包括列名、数据类型和前几行数据。
计算每个产品的总销售额(Price * Quantity)。
打印出每个产品的总销售额。
# 创建向量
product <- c("篮球", "足球", "网球", "排球")
# 创建矩阵
price <- c(100, 50, 80, 30)
quantity <- c(20, 15, 10, 5)
sales_matrix <- matrix(c(price, quantity), ncol = 2, byrow = TRUE)
# 创建数据框
sales_data <- data.frame(Product = product, Price = sales_matrix[, 1], Quantity = sales_matrix[, 2])
# 打印数据框摘要信息
summary(sales_data)
## Product Price Quantity
## Length:4 Min. : 10.0 Min. : 5.0
## Class :character 1st Qu.: 17.5 1st Qu.:12.5
## Mode :character Median : 50.0 Median :22.5
## Mean : 52.5 Mean :25.0
## 3rd Qu.: 85.0 3rd Qu.:35.0
## Max. :100.0 Max. :50.0
# 计算每个产品的总销售额
sales_data$TotalSales <- sales_data$Price * sales_data$Quantity
# 打印每个产品的总销售额
cat("每个产品的总销售额:\n")
## 每个产品的总销售额:
print(sales_data$TotalSales)
## [1] 5000 2400 300 50
数据框与矩阵有类似之处,但用于组织多个存储类型不尽相同的变量。数据框也是一张二维表格。统计上称行为观测、列为变量,计算机则分别称之为记录和域,且变量名对应域名。后续均采用域的称谓。
可通过is函数判断数据对象是否为数据框,基本书写格式:
is.data.frame(对象名)
如果指定对象为数据框,则函数返回结果为逻辑型常量 TRUE,否则为逻辑型常量FALSE
数据框可视为多个具有不同存储类型的向量(变量)的集合。创建数据框就是要指定数据框由哪些向量(变量)组成,这些向量(变量)对应于数据框中的哪些域。可通过 dataframe函数实现,基本书写格式:
data.frame(域名1=向量名1,域名2=向量名2···)
其中,数据框中的数据已事先存储在各向量中,它们分别与各个域一一对应。可通过 names函数显示各个域名,具体书写格式:
names(数据框名)
以北京市空气质量监测数据为例,对于各监测点有监测点名称(SiteName)、监测点类型SiteTypes)、监测点经度(SiteX)和监测点纬度(SiteY)4 个变量。前2个变量为类别型变量,后 2个变量为数值型变量,两者的存储类型不同。组织监测点数据的理想方式是数据框,其中有4个域(Sitename、Sitetypes、Sitex、Sitey)与4 个变量一一对应。代码和部分执行结果如下所示。
#创建数据框
SiteName<-c("东四","天坛","官园","万寿西宫","奥体中心","农展馆","万柳","北部新区","植物园","丰台花园",
"云岗","古城","房山","大兴","亦庄","通州","顺义","昌平","门头沟","平谷","怀柔","密云","延庆","定陵",
"八达岭","密云水库","东高村","永乐店","榆垡","琉璃河","前门","永定门内","西直门北","南三环","东四环")
SiteTypes<-c(rep("城区环境评价点",12),rep("郊区环境评价点",11),rep("对照点及区域点",7),rep("交通污染监控点",5))
SiteX<-c(116.417,116.407,116.339,116.352,116.397,116.461,116.287,116.174,116.207,116.279,116.146,116.184,
116.136,116.404,116.506,116.663,116.655,116.23,116.106,117.1,116.628,116.832,115.972,
116.22,115.988,116.911,117.12,116.783,116.30,116.00,
116.395,116.394,116.349,116.368,116.483)
SiteY<-c(39.929,39.886,39.929,39.878,39.982,39.937,39.987,40.09,40.002,39.863,39.824,39.914,
39.742,39.718,39.795,39.886,40.127,40.217,39.937,40.143,40.328,40.37,40.453,
40.292,40.365,40.499,40.10,39.712,39.52,39.58,
39.899,39.876,39.954,39.856,39.939)
Site<-data.frame(Sitename=SiteName,Sitetypes=SiteTypes,Sitex=SiteX,Sitey=SiteY)
names(Site)
## [1] "Sitename" "Sitetypes" "Sitex" "Sitey"
str(Site)
## 'data.frame': 35 obs. of 4 variables:
## $ Sitename : chr "东四" "天坛" "官园" "万寿西宫" ...
## $ Sitetypes: chr "城区环境评价点" "城区环境评价点" "城区环境评价点" "城区环境评价点" ...
## $ Sitex : num 116 116 116 116 116 ...
## $ Sitey : num 39.9 39.9 39.9 39.9 40 ...
is.data.frame(Site)
## [1] TRUE
fix(Site)
说明
该数据框由4个域组成,分别对应存储类型不尽相同的 4个向量,且这些向量已存在于工作空间中。由于数据框可将存储类型不同的向量集成在一起,故更适合本例数据的组织。
本例中,监测点名称(Sitename)和监测点类型(Sitetypes)的两个域,因其对应的向量为字符串型向量,默认转换为因子,分别有35个和4个因子水平值。
利用fix函数显示部分数据内容,如图2-2所示。
为便于后续数据框的访问,域名最好不与工作空间中的已有向量同名。本例通过英文大小写加以区分。
若创建数据框时各域尚未有与之对应的向量,即数据框是”空的”,可通过以下方式实现。在R的控制台窗口中依次输入以下R语句,观察执行结果
a<-data.frame(x1=numeric(0),x2=character(0),x3=logical(0))
str(a)
## 'data.frame': 0 obs. of 3 variables:
## $ x1: num
## $ x2: chr
## $ x3: logi
说明:数据框a包含3个域,域名分别为x1x2x3,且存储类型依次为数值型、字符串型和逻辑型。这里,numeric(0)表示创建一个不包含任何数据的数值型的域,其他类似。
一方面,可参照矩阵访问方式访问数据框,这里不再赘述。另一方面,数据框由域组成,对数据框的访问即对各个域的访问,可采用更为清晰明了的方式。基本书写格式有以下几种:
数据框名S域名
其中,数据框名与域名之间应用字符”S”隔开,表示访问指定数据框中的指定域
数据框名[[“域名”]]
其中,需访问的域名应用英文双引号括起来。
数据框名[[域编号]]
其中,须指定将访问的域是数据框中的第几个域,域编号取决于数据框创建时的顺序。
数据框名[c[“域名1”,“域名2”,··· ]]
上述方式均须明确指定数据框名,较为烦琐,可通过attach 函数和detach 函数简化访问时的域名书写,基本书写格式:
attach(数据框名)
访问域名函数1
访问域名函数2
…
detach(数据框名)
attach 称为数据框绑定函数,detach 用于解除对数据框的绑定。这两个函数可形象地视为两个”看不见的屏障”。在”屏障”所围成的区域内访问域,无须指定数据框名称。
#Site
#Site[["Sitetypes"]]
#Site[[1]]
#Site[[2]]
#head(Site)
#head(Site$Sitename)
#tail(Site[["Sitename"]])
#head(Site[[1]])
#tail(Site[c("Sitename","Sitetypes")])
#attach(Site)
#head(Sitename)
#detach(Site)
#Sitename
说明
在attach和detach 函数围成的程序代码区域之内,访问域时无须指定数据框的名称;在attach和 detach 函数围成的区域之外,不能省略数据框名,否则,R 会给出对象未找到的错误提示。
数据框中的域名最好不与工作空间中的向量重名。若重名,尽管可以在其围成的区域内略去数据框名书写域名,但实际上访问的并不是域而是工作空间中的同名向量。
attach函数和detach函数必须配对出现,有一个attach 就必须配对出现一个 detach使用时一定要慎重。
与attach和detach函数有类似作用的还有with函数,基本书写格式:
with(数据框名,{
域访问函数1
域访问函数2
…
})
其中,分可形象地比喻为两个”看不见的屏障”,在”屏障”所围成的区域内访问域,无须指定数据框名称。
with(Site,{Sitename})
## [1] "东四" "天坛" "官园" "万寿西宫" "奥体中心" "农展馆"
## [7] "万柳" "北部新区" "植物园" "丰台花园" "云岗" "古城"
## [13] "房山" "大兴" "亦庄" "通州" "顺义" "昌平"
## [19] "门头沟" "平谷" "怀柔" "密云" "延庆" "定陵"
## [25] "八达岭" "密云水库" "东高村" "永乐店" "榆垡" "琉璃河"
## [31] "前门" "永定门内" "西直门北" "南三环" "东四环"
列表是对象的集合,可包含向量、矩阵、数组、数据框甚至列表等。其中的每个对象称为列表的一个成分,且均有一个成分名。可通过 is 函数判断数据对象是否为列表,基本书写格式:
is.list(数据对象名)
如果指定对象为列表,则函数返回结果为逻辑型常量 TRUE,否则为逻辑型常量FALSE。
创建列表函数的基本书写格式:
list(成分名1=对象名1,成分名2=对象名2,···)
其中,对象是工作空间中的已有对象,分别与各个成分一一对应。可通过 names 函数显示各个成分名,具体书写格式:
names(列表名)
列表的访问方式与数据框相同。
例如,在R的控制台窗口中依次输入以下R语句,观察执行结果
a<-c(1,2,3) #创建向量a
b<-matrix(nrow=5,ncol=2) #创建矩阵b
b[,1]=seq(from=1,to=10,by=2)
b[,2]=seq(from=10,to=1,by=-2)
c<-array(1:60,c(4,5,3)) #创建数组c
d<-list(L1=a,L2=b,L3=c) #创建列表d,包含3个成分分别为向量a,矩阵b和数组c
names(d) #显示列表d各成分名
## [1] "L1" "L2" "L3"
str(d) #显示对象d的存储类型和结构信息
## List of 3
## $ L1: num [1:3] 1 2 3
## $ L2: num [1:5, 1:2] 1 3 5 7 9 10 8 6 4 2
## $ L3: int [1:4, 1:5, 1:3] 1 2 3 4 5 6 7 8 9 10 ...
is.list(d) #判断d是否为列表
## [1] TRUE
d$L1 #访问列表d中的成分L1
## [1] 1 2 3
d[["L2"]] #访问列表d中的成分L2
## [,1] [,2]
## [1,] 1 10
## [2,] 3 8
## [3,] 5 6
## [4,] 7 4
## [5,] 9 2
d[[2]] #访问列表d中的第2个成分(L2)
## [,1] [,2]
## [1,] 1 10
## [2,] 3 8
## [3,] 5 6
## [4,] 7 4
## [5,] 9 2
列表是集成各种对象的有效方式。虽然在数据组织时通常并不采纳,但它却是 R 组织各类数据分析结果的重要方式。对此后面的章节将有具体体现。
将 R对象中的数据保存到数据文件中是十分必要的。这里只讨论如何将 R工作空间中的数据保存到文本文件中。
保存数据到文本文件的函数是write.table函数,基本书写格式:
write.table(数据对象名,fle=“文本文件名”sep=“分隔符”
,quote=TRUE/FALSE,append=TRUE/FALSE,na=“NA”row.names=TRUE/FALSEcolnames=TRUE/FALSE)
其中,数据对象一般为向量、矩阵或数据框;参数 file 指定文本文件名;sep 指定文本文件中各数据列间的分隔符;rownames和colnames取TRUE,表示将行编号和变量名写入文本文件,行编号将位于文本文件的第一列,变量名将位于第一行,否则不写入,通常,行编号无须写入文本文件;quote 为 TRUE 表示文本文件中第一行的变量名以及字符串型数据均用双引号括起来,否则无双引号;append 为 TRUE 表示将数据追加到已有文本文件的尾部,为FALSE表示以数据覆盖已有文本文件中的原有内容。
例如:将前述存储在 R 数据框中的北京市空气质量监测点数据,保存到”监测点信息.txt”文本文件中,代码如下。
SiteName<-c("东四","天坛","官园","万寿西宫","奥体中心","农展馆","万柳","北部新区","植物园","丰台花园",
"云岗","古城","房山","大兴","亦庄","通州","顺义","昌平","门头沟","平谷","怀柔","密云","延庆","定陵",
"八达岭","密云水库","东高村","永乐店","榆垡","琉璃河","前门","永定门内","西直门北","南三环","东四环")
SiteTypes<-c(rep("城区环境评价点",12),rep("郊区环境评价点",11),rep("对照点及区域点",7),rep("交通污染监控点",5))
SiteX<-c(116.417,116.407,116.339,116.352,116.397,116.461,116.287,116.174,116.207,116.279,116.146,116.184,
116.136,116.404,116.506,116.663,116.655,116.23,116.106,117.1,116.628,116.832,115.972,
116.22,115.988,116.911,117.12,116.783,116.30,116.00,
116.395,116.394,116.349,116.368,116.483)
SiteY<-c(39.929,39.886,39.929,39.878,39.982,39.937,39.987,40.09,40.002,39.863,39.824,39.914,
39.742,39.718,39.795,39.886,40.127,40.217,39.937,40.143,40.328,40.37,40.453,
40.292,40.365,40.499,40.10,39.712,39.52,39.58,
39.899,39.876,39.954,39.856,39.939)
Site<-data.frame(Sitename=SiteName,Sitetypes=SiteTypes,Sitex=SiteX,Sitey=SiteY)
write.table(Site,file="监测点信息.txt",row.names=FALSE)
说明:首先,将监测点名称、监测点类型、监测点的经度和纬度数据组织于名为 Site的R数据框中。然后,利用 write.table(函数将 Site 内容保存到名为监测点信息txt 的文本文件中。
从程序设计角度看,将频繁变动的数据对象和相对稳定的程序处理功能合理分离,是提高程序通用性的有效方式。简单举例,一个程序如果只能给出特定整数1加2的结果,而不能给出任意整数x加y的结果,那么这个程序的通用性就很差。因为整数1加2与任意整数x加y的运算法则(功能)是完全相同的,但程序却无法支持将相同的处理施加于不同的数据对象上,导致程序通用性低下。其原因之一就是没有将数据对象和程序处理功能恰当分开使得数据一旦发生变化,就必须随之修改程序,数据变动导致程序变动。
数据对象和处理功能的合理分离是必须的。最简单的实现手段:数据以变量(如x,y)而不是常量(如12)的形式出现在程序代码中,变量的具体取值在程序运行时临时从键盘等输入设备”喂入”程序,从而确保程序不随所处理数据的变动而变动。R支持从键盘输入一组数据到指定向量中,函数的基本书写格式:
对象名 <-scan0)
例如:从键盘输入数据102030到向量a中。
xy <- scan()
R 本身附带了很多数据集供学习和研究者共享。为此,应首先了解 R 有哪些数据集,然后再根据实际需要指定使用某个数据集。浏览R数据集目录的函数是 data0。例如:在R控制台窗口输入data0,显示的数据集名和说明信息。
可通过函数 data(“数据集名”)指定加载使用某个数据集。
例如:data(“AirPassengers”),于是,当前工作空间中会出现一个名为AirPassengers的R对象。对象的结构类型通常为向量、矩阵、数组、数据框等,也可能是时间序列(Time Series,TS)等其他复杂类型的对象.
实际案例中的数据往往事先存在于某种格式的文件中。最常见和最通用的文件格式是文本文件,其扩展名一般是txt或csv。可利用read.table 或readcsv 函数,直接将其读入R对象(通常是R数据框)中。基本书写格式:
readtable(file=“文件名txt”,header=TRUE/FALSE,sep=“数据分隔符”,stringsAsFactors=TRUE/FALSE)
或
read.csv(file=“文件名csv”,header =TRUE/FALSE,stringsAsFactors=TRUE/FALSE)
其中,header 取 TRUE 表示文本文件的第一行为标题行,否则为具体数据;sep 指定文本文件中各数据列间的分隔符,省略时默认分隔符为空格、制表符、换行符或回车符。扩展名为csv的文本文件分割符为逗号;stringsAsFactors取 TRUE 或FALSE 表示是否自动将字符型变量转为因子。
以下将通过三个大数据应用案例,介绍如何将文本文件数据读到R的数据框中。
第1章已对北京市空气质量监测数据的内容进行了详尽说明,数据的最终结构见表 1-1。
图2-3为相应文本文件数据的基本结构(文件名:空气质量txt)。
现利用readtable函数将文本数据读到R的数据框中。代码和部分执行结果如下
# MyData<-read.table(file="空气质量.txt",header=TRUE,sep=" ",stringsAsFactors=FALSE)
# str(MyData)
说明:
readtable0函数将文本数据导入指定的数据框中,数据框各域名自动命名为文本文件中各列的标题。数据框包含的域个数,等于文本文件的列数。
对文本文件中的字符串型数据SiteName和SiteTypes,导入时指定不自动转换成因子。上述数据结构是加工整理后的结果,从官网下载的原始数据格式见表 1-2,且一个数据文件中只包含一天的监测数据。因此将一年所有天的数据合并在一起,并进行格式转换,是该案例分析的前提。将在3.55节对该问题做详细讨论。
表2-1是北京市3958个美食餐馆的食客点评数据(文件名:美食评分数据csv)。其中shop ID为餐馆编号;review n为一段时间内食客发表评论的评论数目;taste、environment、serivce 为食客对餐馆菜看口味、就餐环境、服务质量打分的平均值,满分40分。scoreavg为平均的综合得分,满分5分;cost avg 为人均消费金额。
表2-2是表 2-1 中美食餐馆的信息数据(文件名:餐馆信息csv)。其中,region 为餐馆所在区域;shop_ID为餐馆编号;food type 为餐馆主打菜。
基于上述两张表中的数据,可首先将两份数据合并,并在此基础上做很多方面的数据分析。后续将给出详细的分析示例。
这里,仅利用read.table 函数将两张表的数据读入R数据框中。代码和部分执行结果如下。
# MyData<-read.table(file="美食评分数据.csv",header=TRUE,sep=",",stringsAsFactors=FALSE)
# str(MyData)
# MyData$shop_ID<-as.character(MyData$shop_ID)
# str(MyData)
# MyData<-read.table(file="餐馆信息.csv",header=TRUE,sep=",",stringsAsFactors=FALSE)
# str(MyData)
# MyData$shop_ID<-as.character(MyData$shop_ID)
说明:利用 str()函数浏览数据结构发现,两份数据中的美食餐馆编号的存储类型均默认为数值型。可利用as.character0函数将其转换为字符串型。
表2-3是超市顾客购买行为的部分数据(文件名:顾客交易数据txt)。其中,CardID为顾客会员卡号;Date为购物日期;Amount为消费金额。
该份数据具有典型的顾客交易行为大数据的特点,基于交易行为的顾客画像是非常普遍且重要的大数据分析应用。仅就表 2-3 数据而言,可分析的内容非常有限,须对此做进一步的数据整理以获得内涵更为丰富的数据。
这里,仅利用read.table函数将数据读入R数据框中。代码和部分执行结果如下。
# MyData<-read.table(file="顾客交易数据.txt",header=TRUE,sep=",",stringsAsFactors=FALSE)
# str(MyData)
向量操作: 给定两个向量x和y,分别为:
{r} x <- c(1, 2, 3, 4, 5) y <- c(6, 7, 8, 9, 10)}
请编写R代码完成以下操作:
计算x和y的和。
计算x和y的差。
计算x和y的乘积。
计算x和y的元素间的平均值。
2.数据框操作: 给定一个名为”mydata”的数据框,包含以下内容:
{r} mydata <- data.frame( 姓名 = c("Alice", "Bob", "Cathy"), 年龄 = c(25, 30, 35), 性别 = c("女", "男", "女") )}
请编写R代码完成以下操作:
输出”mydata”的前两行数据。
计算”mydata”中年龄的平均值。
添加一列”学历”,值为c(“本科”, “硕士”, “本科”)。
选择性别为”女”的行。