R语言-数据类型、结构以及对象类型4
目录
1. 向量(vector)
2. 因子(factor)
3. 矩阵(matrix)
4. 列表(list)
5. 数据框(data frame)
6. 特殊值数据
7. 获取数据类型信息的一些有用函数
1. 向量(vector)
我们通常接触的数据主要是数字、字符和逻辑(真和假,是或不是)类型的。数据有一个个的,也有一串串一批批的。在R里面,最基本的数据类是向量,即一串有序数据;但vector是虚拟类,没有父类型,它包含了在其他语言里面常说的基本数据类型如整型、字符型和逻辑型等:
getClass("vector")
R语言处理数据的最基本单位是向量,而不是原子数据。所以向量又称为原子向量(atomic vector),R语言的数据单位里面它最小(也最大,没有谁是它的父母)。但由于vector是虚拟类,不管用什么方式你都不可能获得类型名称叫“vector”的对象,只能获得它的直接子类的对象。下面的x是一个矩阵,虽然我们用as.vector函数进行转换,但获得对象的类名称是integer而不是vector:
> x <- matrix(1:4, nrow=2)
> class(x)
[1] "matrix"
> class(as.vector(x))
[1] "integer"
一个向量可以是一串数字(n个数字,向量长度为n),也可以是1个数字(向量长度为1):
> x=1:40
> 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 24
[25] 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
> x=1
> x
[1] 1
等于号可以用于向量赋值,但符号“<-”更常用,更好,更专业:
> x <- c(1,2,3)
> x
[1] 1 2 3
c( )是R的一个函数,表示将括号里面的内容连接起来成为一个向量。R提供了一些产生特殊向量的函数,如seq( )和rep( ),具体用法直接在R里面先输入问号(?)和函数名去查询。vector是虚拟类,本身不指定数据的存储类型,但赋值以后就马上会有数字型(numeric)、字符型(character)、逻辑型(logical)等实际类别,比如上面的变量x和y,用class( )函数获得的类型分别是数值型和字符型:
> class(x)
[1] "numeric"
一个向量只属于一种类型,如果改变了一个元素的值可能会改变该向量的类型:
> x <- seq(10)
> x
[1] 1 2 3 4 5 6 7 8 9 10
> class(x)
[1] "integer"
> x[2] <- "Adam"
> x
[1] "1" "Adam" "3" "4" "5" "6" "7" "8" "9" "10"
> class(x)
[1] "character"
向量元素的引用/提取用下标法如 x[2],R语言的下标从1开始编号(而不是0)。
2. 因子(factor)
R定义了一类非常特殊的数据类型:因子。比如我们的实验获得了10个数据,前5个数据来自对照样品CK,其余属于处理样品TR,R语言中可以用下面方法标识这10个数据的样品属性:
> sample <- rep(c("CK","TR"), each=5)
> sample<- factor(sample)
> sample
[1] CK CK CK CK CK TR TR TR TR TR
Levels: CK TR
因子的种类称为水平(level)。上面的样品sample因子有两个水平:CK和TR。因子类数据很特殊:
getClass("factor")
使用因子类数据是因为R是针对统计应用的语言。使用因子以后,数据的统计会完全不同。比如上面的两个样品10个测定数值如果是:
value <- rnorm(10)
value
求样品的平均值就可以这么做:
> tapply(value, sample, mean)
CK TR
0.37757771 -0.07713458
gl( )函数也可以方便地产生因子:
> sample <- gl(2, 5, labels = c("CK", "TR"))
> sample
[1] CK CK CK CK CK TR TR TR TR TR
Levels: CK TR
因子操作常用函数:
常用函数中的tapply,aggregate,by三个函数参数类似,但是其作用范围有所不同。cut函数是构建因子常用方法,而reshape2包里的 melt,cast 函数可以对更加灵活地对数据重构和创建因子。
Function | introduce |
---|---|
tapply(x, f, g) | x是向量,f是因子列,g是操作函数。 |
aggregate(x, f, g) | x是数据框或矩阵,f是因子列,g是操作函数,对x中的每一列都进行tapply的操作,tapply的扩展。 |
by(x, f, g) | x是矩阵或者数据框,f是因子列,g是操作函数,按照列表分组后,对分组后数据进行整体操作 |
cut(x,b,labels) | x是向量,b是breaks,labels是levels名(默认FLASE,为1,2,3···),连续型变量生成因子的一种常用方法 |
split(x, f) | x是向量或者数据框,f是因子列,将向量或者数据框根据因子切分成组,返还列表格式 |
unsplit(x, f) | x列表,f是因子列,将列表格式,返还向量格式 |
##tapply,对mtcars的mpg列根据am,carb分类求均值
tapply(mtcars$mpg, list(mtcars$am, mtcars$carb), mean)
1 2 3 4 6 8
0 20.33 19.30 16.3 14.30 NA NA
1 29.10 27.05 NA 19.27 19.7 15
##aggregate,对mpg的前3列根据am进行求均值
aggregate(mtcars[,1:3],list(mtcars$am), mean)
Group.1 mpg cyl disp
1 0 17.15 6.95 290.38
2 1 24.39 5.08 143.53
##by, 根据am分组后,对数据进行summary
by(mtcars[,1:3],list(mtcars$am),summary)
: 0
mpg cyl disp
Min. :10.40 Min. :4.000 Min. :120.1
1st Qu.:14.95 1st Qu.:6.000 1st Qu.:196.3
Median :17.30 Median :8.000 Median :275.8
Mean :17.15 Mean :6.947 Mean :290.4
3rd Qu.:19.20 3rd Qu.:8.000 3rd Qu.:360.0
Max. :24.40 Max. :8.000 Max. :472.0
----------------------------------------------------------------------------
: 1
mpg cyl disp
Min. :15.00 Min. :4.000 Min. : 71.1
1st Qu.:21.00 1st Qu.:4.000 1st Qu.: 79.0
Median :22.80 Median :4.000 Median :120.3
Mean :24.39 Mean :5.077 Mean :143.5
3rd Qu.:30.40 3rd Qu.:6.000 3rd Qu.:160.0
Max. :33.90 Max. :8.000 Max. :351.0
###cut,将第一列数据分成10组并用,1,2,3···标注。
(binmarks <- seq(from=min(mtcars$mpg), to=max(mtcars$mpg), length.out=10))
[1] 10.40 13.01 15.62 18.23 20.84 23.46 26.07 28.68 31.29 33.90
cut(mtcars$mpg, binmarks, labels = F)
[1] 5 5 5 5 4 3 2 6 5 4 3 3 3 2 NA NA 2 9 8 9 5 2 2 2 4 7 6 8 3 4 2 5
##split,按照am对Mtcars进行切分
split(mtcars, list(mtcars$am))
require(stats); require(graphics)
n <- 10; nn <- 100
g <- factor(round(n * runif(n * nn)))
x <- rnorm(n * nn) + sqrt(as.numeric(g))
xg <- split(x, g)
boxplot(xg, col = "lavender", notch = TRUE, varwidth = TRUE)
class(sapply(xg, length))
sapply(xg, mean)
z <- unsplit(lapply(split(x, g), scale), g)
3. 矩阵(matrix)
矩阵的继承关系比较复杂,它和数组(array)的关系既是父亲又是儿子,还是孙子:
getClass("matrix")
如果你愿意,也可以把矩阵称为数组,但事实上它们是不同的类。生物类数据以二维数组/矩阵居多。向量数据可以转成矩阵,下面代码将10个元素的x转成2行5列的矩阵:
> x <- 1:10
> dim(x) <- c(2,5)
> x
[,1] [,2] [,3] [,4] [,5]
[1,] 1 3 5 7 9
[2,] 2 4 6 8 10
> dim(x)
[1] 2 5
dim( )是一个函数,它获取或设置数据的维度。注意x数据的行列排列顺序:先列后行。但是矩阵内数据的下标读取方式是先行后列。x[2, 1]是第2行第1列的值,x[2, ]表示第2行的所有数据,x[ ,2]表示第2列的所有数据。
> x[2,1]
[1] 2
> x[2,]
[1] 2 4 6 8 10
> x[ ,2]
[1] 3 4
把1个向量转成矩阵还可以使用matrix( )函数,参数nrow设置行数,ncol设置列数:
> matrix(1:10, nrow=2)
[,1] [,2] [,3] [,4] [,5]
[1,] 1 3 5 7 9
[2,] 2 4 6 8 10
几个长度相同的向量也可以合并到一个矩阵,cbind( )函数将每个向量当成一列(按列)合并,rbind( )按行合并:
> x <- 3:6
> y <- 4:7
> z <- 1:4
> cbind(x,y,z)
x y z
[1,] 3 4 1
[2,] 4 5 2
[3,] 5 6 3
[4,] 6 7 4
> rbind(x,y,z)
[,1] [,2] [,3] [,4]
x 3 4 5 6
y 4 5 6 7
z 1 2 3 4
不同向量的数据类型要相同,否则转换成矩阵后数据类型会变样。下面代码将height内的数字全都转成了字符类型,这可能不是你想要的结果:
> name <- c("赵", "钱", "孙")
> height <- c(142, 165, 188)
> info <- rbind(name,height)
> info
> class(info)
[1] "matrix"
身高是数值,但跟姓名混合组成矩阵后就变成字符型了(输出结果中用双引号引起来)。矩阵元素可通过下标引用,多维矩阵可以只用一个下标,请注意info[3]获得的数据:
> info[1,]
> info[,1]
> info[3]
[1] "钱"
4. 列表(list)
列表由向量直接派生而来,nameList是它的子类,listOfMethods是它家孙子:
getClass("list")
那么列表是什么样子的呢?看这:
> gene <- list(agi="a", mode=c("b", "c", "d"), expression=matrix(1:10, ncol=5))
> gene
列表可以组合不同的数据类型,甚至可以是其他列表,各组成数据的类、长度、维数都可以不一样。
5. 数据框(data frame)
R语言提供了另外一种更灵活的数据类型:数据框。可以将几个不同类型但长度相同的向量用data.frame( )函数合并到一个数据框,它的模样就像二维数组。但要注意:合并的几个向量长度必需一致。
getClass("data.frame")
用as.data.frame( )函数可以将二维矩阵转成数据框,虽然数据框的外观和二维矩阵差不多,但它却不是从矩阵而是从列表派生来的,它是数据(.data)是列表数据,列名称(names)就是列表中各项的名称,另外还有行名称(row.names)。
数据框的每列是一个向量,称为列向量。列向量只有两种类型,要么是数字型,要么是因子型。从文件读取或其他类型数据转换成数据框的数据,如果不是数值型,会被强制转换成因子型。有时候数值型(尤其是整型)向量也会被转成因子,这点应该注意。
数据框可以用数字下标取数据,也可以用列名称下标取数据,但是两种方式所获数据的类型是不一样的,按列名称下标方式取得的数据仍然是数据框:
# 数据框常用语句
> info[,1]
[1] 赵 钱 孙
Levels: 钱 孙 赵
> class(info[,1])
[1] "factor"
> info["name"]
name
1 赵
2 钱
3 孙
> class(info["name"])
[1] "data.frame"
为什么要注意这个区别?因为看起来像是同样的数据,在一些对类型要求很严格的操作(比如作图)中得到完全不一样的结果。数据框还有一种数据提取方式,得到因子或向量:
> class(info$name)
[1] "factor"
> class(info$height)
[1] "numeric"
6. 特殊值数据
为确保所有数据都能被正确识别、计算或统计等,R定义了一些特殊值数据:
NULL:空数据
NA:表示无数据
NaN:表示非数字
inf:数字除以0得到的值
判断一个object (x)是不是属于这些类型有相应的函数:
is.null(x)
is.na(x)
is.nan(x)
is.infinite(x)
7. 获取数据类型信息的一些有用函数
R语言的对象“类”很多,虽然我们不可能一一去详细学习,但接触到一类新数据时我们需要了解一些基本信息才能进行进一步的操作。R提供了一些非常有用的方法(函数)。
getClass() 函数我们前面已经见过了,它的参数是表示类的字符串。
class() 可获取一个数据对象所属的类,它的参数是对象名称。
str() 可获取数据对象的结构组成,这很有用。
mode()和 storage.mode()可获取对象的存储模式。
typeof() 获取数据的类型或存储模式。
要了解这些函数能干什么可以在R里面查询,方法是用问号加上面的函数名就可以,如:?str
©哈尔滨商业大学 银河统计工作室
银河统计工作室成员由在校统计、计算机部分师生和企业数据数据分析师组成,维护和开发银河统计网和银河统计博客(技术文档)。专注于数据挖掘技术研究和运用,探索统计学、应用数学和IT技术有机结合,尝试大数据条件下新型统计学教学模式。