数据集 | 含义 |
---|---|
AirPassenger | Box &Jenkins航空公司1949年~1960年每月国际航线乘客数 |
airquality | 纽约市1973年5月~9月每日空气质量 |
cars | 20世纪20年代汽车速度对刹车距离的影响 |
mtcars | 1974年美国Motor Trend杂志上刊登的32辆车的11个指标数据 |
Titanic | “泰坦尼克”号生还者信息,包括舱室(一等舱、二等舱、三等舱)、性别、年龄、是否生还 |
InsectSprays | 使用6种杀虫剂后各自的害虫存活率 |
Orange | 橙树的种类、树龄、树围 |
SWiSS | 1888年前后,瑞士联邦47个法语州的生育率与社会经济指标(农业从业者比例、入伍考试成绩、教育等) |
read.csv( #将csv文件读入数据框
file, #文件名
header=FALSE, # 是否指定文件第一行为标题
#数据中含有缺失值时,指定与R的NA相对应的值。
#默认值为"NA”,保存为"NA的字符串会被保存为R中的NA。
na.strings="NA",
#用于指定将字符串保存为因子还是字符串。
#若不设置,则采用默认值TRUE,即转换成因子。
stringsAsFactors=default.stringsAsFactors()
) #返回值为数据框。
write.csv( #将数据框保存为CSv文件
X, #要保存在文件中的数据框或矩阵
file="", #保存数据的文件名
row.names=TRUE #若为TRUE,则将行名也保存到csV文件。
)
有时,数据中可能含有表示NA的字符串,在使用read.csv()函数读入这些数据时,会被转换为因子,这会导致整个列都被转换为因子。此时,使用na.strings参数可以避免这一问题。na.strings参数的默认值为NA,这意味着数据中的NA字符串会被转换为R能够识别的NA值。
R中有save()、load()两个函数,使用它们可以将R对象保存到二进制文件,也可以从二进制文件中读取R对象。
save( #将内存中的对象保存到文件
…, #要保存的对象名
list=character(), #将要保存的对象名设置为向量时,用于代替···
file #文件名
)
# 例如
save(list=ls(),file="abc.RData") #将内存中所有的对象保存在指定文件中
load( #将对象从指定文件读入内存
file #文件名
) #返回值为保存对象名称的向量,这些对象是从文件读入的
函数 | 含义 |
---|---|
rbind(…) | 按行合并指定数据 |
cbind(…) | 按列合并指定数据 |
# 例如
rbind(c(1,2,3),c(4,5,6))
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
x <-data.frame(id=c(1,2),name=c("a","b"),stringsAsFactors=F)
#设置stringsAsFactors=FALSE保证其不会被转换为因子
rbind(x,c(3,"c"))
id name
1 1 a
2 2 b
3 3 c
cbind(c(1,2,3),c(4,5,6))
[,1] [,2]
[1,] 1 4
[2,] 2 5
[3,] 3 6
函数 | 说明 | 特性 |
---|---|---|
apply() | 向数组或矩阵应用指定函数,然后将结果值以向量、数组或列表形式返回 | 适用于数组或矩阵 |
lapply() | 向向量、列表或表达式应用函数,并以列表形式返回结果sapply() 与lapply()类似,但以向量、矩阵或数组形式返回结果 | 返回列表 |
tapply() | 根据指定标准对向量中的数据分组,然后对每个分组应用指定函数,并返回结果 | 返回向量、矩阵或数组 |
mapply() | sapply()函数的扩展版本,借助参数接收多个向量或列表,然后针对各数据的第一个元素应用函数计算结果,然后针对第二个元素,再针对第三个元素……以此类推,最后返回所有计算结果 | 将多个数据应用为函数参数 |
apply()函数按矩阵的行或列方向应用指定函数。
apply( #沿MARGIN方向,向数组或矩阵应用函数FUN,并以向量、数组或列表形式返回结果。
X, #数组或矩阵
MARGIN,#应用函数的方向。1是沿行方向,2是沿列方向。
#C(1,2)表示同时沿行与沿列方向。
FUN #要应用的函数
) #FUN函数返回长度为1的向量时,返回向量;
#返回大于1的向量时,返回矩阵;
#返回长度不同的向量时,返回列表。
#例如:使用apply()函数对矩阵应用求和函数,计算矩阵中保存的数据之和。
d <- matrix(1:9,ncol=3)
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
apply(d,1,sum)
[1] 12 15 18
apply(d,2,sum)
[1] 6 15 24
R还专门定义了rowSums()、rowMeans()、colSums()、colMeans()函数,对行或列进行求和或均值计算。
lapply()函数以列表形式返回应用函数的结果。
lapply( #向列表、向量、表达式、数据框等应用指定函数,并将结果以列表形式返回。
X, #向量、列表、表达式或数据框
FUN, #待应用的函数
… #额外参数,这些参数会被传递给FUN函数。
) #返回值为与x等长的列表。
从使用角度看,向量与数据框比列表更直观,所以有必要转换lapply()的结果。此时,可以使用下面所示的两个函数,将列表转换为其他数据类型。
unlist( #将列表转换为向量。
x, #R对象,一般为列表或向量
recursive=FALSE, #是否对x中的列表进行递归转换
use.names=TRUE #是否保留列表中的值名称
) #返回向量
do.call( #调用指定函数,将以列表形式给出的参数传递给被调用函数,返回函数调用结果。
what, #要调用的函数
args, #要传递给函数的参数列表
) #返回值为函数调用结果
下面通过lapply()函数对向量c(1,2,3)中的每个数进行“乘2”运算。
(result <- lapply(1:3,function(x) {x*2}))
[[1]]
[1] 2
[[2]]
[1] 4
[[3]]
[1] 6
unlist(result)
[1] 2 4 6
lapply()函数可以接收列表作为参数。例如,使用lapply()函数为列表中的每个变量计算平均值。
x <- list(a=1:3,b=4:6)
lapply(x,mean)
$a
[1] 2
$b
[1] 5
使用lapply()函数处理数据框后得到列表,有时可能需要将得到的列表再次转换为数据框。转换处理需要经过如下几个阶段。
下列示例中,先使用lapply)函数对鸢尾花数据集的前4列分别求平均值,然后将结果再次转换为数据框。
d <- as.data.frame(matrix(unlist(lapply(iris[, 1:4), mean)),ncol=4,byrow=TRUE))
names (d)<- names (iris [, 1:4])
d
Sepal.Length Sepal.Width Petal.Length Petal.Width
1 5.843333 3.057333 3.758 1.199333
此外,还可以使用do.call()函数进行类型转换。前面示例中,对鸢尾花数据集的前4列数据应用lapply()函数后,求出各列平均值,并存放到列表。接下来,可以使用cbind()函数将这些平均值合并为新数据框的列。下列代码中,使用do.call()函数,将lapply()函数返回的列表中的各元素作为参数传递给cbind()函数。
data.frame(do.call(cbind, lapply(iris[, 1:4], mean)))
Sepal.Length Sepal.Width Petal.Length Petal.Width
1 5.843333 3.057333 3.758 1.199333
上述两种方法中,使用第一种方法(先使用unlist(函数将列表转换为向量,再使用matrix()函数将向量转换为矩阵时会有一个问题,那就是使用unlist()函数将列表转换为向量后,由于向量中只能保存1种数据类型,所以转换过程中,所有数据都会被转换为同一数据类型。当列表中同时存在字符串与数值时,使用unlist()函数将列表转换为向量后,所有字符串都被转换为莫名其妙的数值。 因此,列表中有不同数据类型的数据时,必须使用do.call()函数进行类型转换。
sapply()函数与lapply()函数类似,但以矩阵、向量等数据类型返回结果。
sapply:向列表、向量、表达式、数据框等应用指定函数,然后以向量或矩阵形式返回结果。
sapply(
X, #向量、列表、表达式、数据框
FUN, #待应用的函数
···, #额外参数,这些参数将传递给FUN函数。
)
使用as.data.frame()函数可以将sapply()函数返回的向量进一步转换为数据框。此时,若不使用t(x)函数转置向量的行与列,将无法得到想要的数据框。下列示例中,先使用sapply()函数对鸢尾花数据集的前4列分别求平均值,得到包含平均值的向量后,再使用as.data.frame()函数将向量转换为数据框。
x <- sapply(iris[, 1:4], mean)
as.data.frame(x)
X
Sepal.Length 5.843333
Sepal.Width 3.057333
Petal.Length 3.758000
Petal.Width 1.199333
as.data.frame(t(x))
Sepal.Length Sepal.Width Petal.Length Petal.Width
1 5.843333 3.057333 3.758 1.199333
处理包含多列的数据框时,常常需要判断各列的数据类型,比如判断某列中保存的数据是否为数值。此时,使用sapply()函数能够很方便地进行判断。下列示例中,使用sapply()函数判断鸢尾花数据集中各列的数据类型。
sapply(iris,class)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
“numeric” “numeric” “numeric” “numeric” “factor”
向量或矩阵只能保存同种数据类型的数据,而sapply()函数返回的是向量或矩阵,因此,作为sapply()函数的参数传入的FUN函数返回值中,不能混有多种数据类型。若对各列应用函数后所得结果的数据类型彼此不同,此时应该使用返回列表的lapply()函数,或者plyr包中的相关函数。
apply系列函数中,使用tapply()函数会先对数据进行分组,然后将函数应用到各组。
tapply( #根据给定的标准,对向量中保存的数据进行分组,然后对各分组应用指定函数,并返回结果。
X, #向量
INDEX, #数据分组索引。该参数应该被设置为因子,非因子的数据类型会被自动转换为因子。
FUN, #要向各分组应用的函数
···, #额外参数,这些参数将被传递给FUN函数。
) #返回值为数组。
下列示例中,将1~10的10个数字全部划分到一个分组,对该分组中的所有数据求和,得到数据总和55。
tapply(1:10, rep(1, 10), sum)
1
55
上述示例代码中,rep(1,10)表示将1重复10次。因此,数字1、2、3···10拥有相同的分组编号,分别为1、1、1…1,即它们都属于分组1,对分组1中的数据求和,得到55(=1+2+3+···+10)。
接下来,将1~10的10个数字划分到偶数与奇数两个分组中,再对两个分组分别求和。在INDEX参数中使用x%%2=1作为分组标准,将10个数字分别划分到偶数组与奇数组。
tapply(1:10, 1:10 %% 2 == 1, sum)
FALSE TRUE
30 25
运行上述代码后,得到偶数和为30(=2+4+6+8+10)、奇数和等于25(=1+3+5+7+9)。
ps:文章用于学习
[参考书目] 徐珉久,R语言与数据分析实战,2017