重要函数:
处理循环:R不仅有for/while语句,还有更强大的实现循环的“”一句话”函数:
例如:lapply,sapply,apply,mapply,tapply
排序: sort, order
总结数据信息:
1. lapply: 循环处理列表的每一个元素的函数
lapply(列表,函数/函数名,其他参数), 如果输入的不是列表会强制转换成列表,且总是返回一个列表。
>str(lapply) #将对象以简洁的方式展现出来,可以用这个函数查看某些函数的使用方式等
function (X, FUN, ...)
>x=list(a=1:10,b=c(11,21,31,41,51))
>lapply(x,mean) #对列表x中的每一个元素执行函数mean功能,并返回一个列表
$a
[1] 5.5
$b
[1] 31
#runif函数,从一个均匀分布的整体里抽取若干个数,没有设定min和max,则默认从0到1间抽取。
>x=1:4
>lapply(x,runif)#对向量x中的每一个元素执行函数runif函数功能 ,此处x输入lapply时就强制转换成了列表
[[1]]
[1] 0.5071569
[[2]] #x的第2个元素为2,表示使用runif函数从0到1中抽取2个元素
[1] 0.7498979 0.4167026
[[3]]
[1] 0.3318948 0.7376890 0.8953933
[[4]]
[1] 0.3661408 0.8690727 0.7495184 0.6303936
##runif函数加min和max参数,表示抽取范围为min到max之间。
>x=1:4
>lapply(x,runif,min=0,max=100)
[[1]]
[1] 33.60319
[[2]]
[1] 10.39440 15.01912
[[3]]
[1] 40.760076 80.177156 8.579981
[[4]]
[1] 36.112842 5.754629 52.333730 20.258521
lapply函数总是和匿名函数一起使用
>x=list(a=matrix(1:6,2,3),b=matrix(4:7,2,2))
>lapply(x,function(m) m[1,]) #匿名函数m设置的功能是取出矩阵的第一行;将这个函数使用到列表x的每一个矩阵中
$a
[1] 1 3 5
$b
[1] 4 6
拓展:sapply函数
sapply函数和apply函数非常像,不同的是它可以将apply的结果进行化简(如果能化简的前提下)
>x=list(a=1:10,b=c(11,21,31,41,51))
> lapply(x,mean)
$a
[1] 5.5
$b
[1] 31
> class(lapply(x,mean))
[1] "list"
#sapply在lapply的基础上进行了简化,将lapply的返回值列表简化成一个向量。
> sapply(x,mean)
a b
5.5 31.0
> class(sapply(x,mean))
[1] "numeric"
总结:
lapply:可以循环处理列表中的每一个元素,lapply(列表,函数/函数名,其他参数),总是返回一个列表。
sapply:简化结果:
结果列表元素长度均为1,返回向量;
结果列表元素长度相同且大于1,返回矩阵。
结构列表元素长度不相同,则无法返回向量或矩阵,则无法简化,此时返回结果与lapply返回结果一样。
2. apply函数
apply的作用是沿着矩阵或数组的某一个维度处理数据。
apply(数组,维度,函数/函数名)
##apply用于矩阵上时,表示沿着矩阵的行或列应用某个函数
>x=matrix(1:16,4,4)
>apply(x,2,mean) #2表示沿着第二维度(即按列),mean表示求平均
[1] 2.5 6.5 10.5 14.5
>apply(x,2,sum) #sum表示求和
[1] 10 26 42 58
###求和求平均的函数还可以用以下函数
>rowSums(x) #按行求和
>rowMeans(x) #按行求平均
>colSums(x)
>colMeans(x)
###apply函数更复杂的用法
>x=matrix(rnorm(100),10,10) #随机从正态分布(默认mean=0,sd=1)里抽取100个数,排成10行10列的矩阵
>apply(x,1,quantile, probs=c(0.25,0.75)) #quantile函数功能是取百分位点,probs参数限定取百分位点0.25和0.75对应的数据
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
25% -0.8698191 0.1834426 -0.7151516 -0.7226345 -0.4760617 -0.3621392 0.3263838 -0.9957614 -0.8140163
75% 0.1321196 0.9225007 0.3939212 0.3600644 0.8427925 0.6938235 1.0108419 0.5014759 0.4611247
[,10]
25% -0.7366401
75% 0.7528281
##apply在数组上的应用
>x=array(rnorm(2*3*4),c(2,3,4))
>apply(x,c(1,2),mean)
[,1] [,2] [,3]
[1,] 0.6826388 -0.05148654 0.6598627
[2,] 0.9493935 1.07309431 0.1900946
3. mapply函数的使用
mapply是lapply的多元版本,mapply(函数/函数名,数据,函数相关参数)
##例1:
> list(rep(1,4),rep(2,3),rep(3,2),rep(4,1))
[[1]]
[1] 1 1 1 1
[[2]]
[1] 2 2 2
[[3]]
[1] 3 3
[[4]]
[1] 4
>mapply(rep,1:4,4:1) #等价于上面使用4次rep
[[1]]
[1] 1 1 1 1
[[2]]
[1] 2 2 2
[[3]]
[1] 3 3
[[4]]
[1] 4
将mapply与自定义的函数结合使用
使用function(参数1){函数(参数2)}设置自己想要的函数,参数1和2保持一致。
>s=function(n,mean,std){rnorm(n,mean,std)} #定义一个取正态分布的函数s
>s(4,0,1) #从均值为0标准差为1的正态分布里抽取4个数据
[1] 0.02827703 0.78118912 -2.21107882 -1.32102919
>list(s(1,5,2),s(2,4,2),s(3,3,2),s(4,2,2),s(5,1,2))#生成一个列表
[[1]]
[1] 3.540876
[[2]]
[1] 7.051226 1.943815
[[3]]
[1] 1.6773376 0.5642655 -0.9923016
[[4]]
[1] 4.479538 2.996352 2.874110 2.378267
[[5]]
[1] 1.2305284 2.4137494 -0.9950734 -1.7734084 1.1782496
#以上生成列表的方法可以用mapply函数快速生成
>mapply(s,1:5,5:1,2) #1:5对应s()函数中的第1个参数4,5:1对应s()函数中的第2个参数0,2对应s()函数中的第3个参数1.
[[1]]
[1] 3.540876
[[2]]
[1] 7.051226 1.943815
[[3]]
[1] 1.6773376 0.5642655 -0.9923016
[[4]]
[1] 4.479538 2.996352 2.874110 2.378267
[[5]]
[1] 1.2305284 2.4137494 -0.9950734 -1.7734084 1.1782496
4. tapply函数的使用
tapply函数对向量的子集进行操作,tapply(向量,因子/因子列表,函数名)
>x=c(rnorm(5),runif(5),rnorm(5,1)) #创建包含15个元素的向量,分别来自正态分布,均匀分布和均值为1的正态分布
>f=gl(3,5) #使用gl()函数创建一个因子,这个因子包含3个水平,每个水平下5个元素
[1] 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3
Levels: 1 2 3
>tapply(x,f,mean) #使用tapply()函数,对向量x,按照f因子进行分组,对每一组求均值。
1 2 3
-0.4139614 0.6019100 0.3027485
#tapply函数有一个默认参数simplify=TRUE,这个参数的功能是对返回值进行简化,如:将返回的列表简化成矩阵形式。
>tapply(x,f,mean,simplify=FALSE) #使simplify参数为FALSE,返回值是一个列表。
$`1`
[1] -0.4139614
$`2`
[1] 0.60191
$`3`
[1] 0.3027485
5.split函数的使用
split函数的作用是根据因子或因子列表将向量或其他对象分组,通常与lapply一起使用。
split(向量/列表/数据框,因子/因子列表)
###例1:还是使用上面的例子
>x=c(rnorm(5),runif(5),rnorm(5,1))
>f=gl(3,5)
>split(x,f)
$`1`
[1] 2.4163880 0.3688412 -0.8332317 -1.2660243 -0.1656017
$`2`
[1] 0.4877443 0.1797565 0.7013813 0.2955032 0.1029182
$`3`
[1] -0.09358635 2.94570706 0.71325020 1.05274496 0.71446343
>lapply(split(x,f),mean) #lapply函数对分组后的列表按照每个元素取均值
$`1`
[1] 0.1040743
$`2`
[1] 0.3534607
$`3`
[1] 1.066516
###例2:使用R内置的数据集
>head(airquality)
Ozone Solar.R Wind Temp Month Day
1 41 190 7.4 67 5 1
2 36 118 8.0 72 5 2
3 12 149 12.6 74 5 3
4 18 313 11.5 62 5 4
5 NA NA 14.3 56 5 5
6 28 NA 14.9 66 5 6
>s=split(airquality,airquality$Month) #按照月份对这个数据框进行分组
>table(airquality$Month) #含有5个月,每个月下有不同的记录数
5 6 7 8 9
31 30 31 31 30
>lapply(s,function(x)colMeans(x[,c("Ozone","Wind","Temp")]))
$`5`
Ozone Wind Temp
NA 11.62258 65.54839
$`6`
Ozone Wind Temp
NA 10.26667 79.10000
$`7`
Ozone Wind Temp
NA 8.941935 83.903226
$`8`
Ozone Wind Temp
NA 8.793548 83.967742
$`9`
Ozone Wind Temp
NA 10.18 76.90
#使用sapply()函数进行简化
> sapply(s,function(x)colMeans(x[,c("Ozone","Wind","Temp")]))
5 6 7 8 9
Ozone NA NA NA NA NA
Wind 11.62258 10.26667 8.941935 8.793548 10.18
Temp 65.54839 79.10000 83.903226 83.967742 76.90
#在colMeans这个函数中加入参数na.rm=TRUE去除缺失值所在行。
>sapply(s,function(x)colMeans(x[,c("Ozone","Wind","Temp")],na.rm=TRUE))
5 6 7 8 9
Ozone 23.61538 29.44444 59.115385 59.961538 31.44828
Wind 11.62258 10.26667 8.941935 8.793548 10.18000
Temp 65.54839 79.10000 83.903226 83.967742 76.90000
6. 排序
sort函数对向量进行排序,返回排好序的内容;
order函数返回排好序的内容的下标,并且可以按照多个排序标准进行排序
>x=data.frame(v1=1:5,v2=c(10,7,9,6,8),v3=11:15,v4=c(1,1,2,2,1))
>x
v1 v2 v3 v4
1 1 10 11 1
2 2 7 12 1
3 3 9 13 2
4 4 6 14 2
5 5 8 15 1
>sort(x$v2) #sort返回排好序的内容,默认升序
[1] 6 7 8 9 10
>sort(x$v2,decreasing=TRUE)
[1] 10 9 8 7 6
> order(x$v2) #sort返回排好序的下标,默认升序
[1] 4 2 5 3 1
> x[order(x$v2),] #因为order返回排好序的下标,所以可以利用这个对数据框进行排序
v1 v2 v3 v4
4 4 6 14 2
2 2 7 12 1
5 5 8 15 1
3 3 9 13 2
1 1 10 11 1
###按照多个排序标准对数据框排序
>x[order(x$v4,x$v2),] #先按照v4升序,在v4变量一致的前提下再按照v2升序
v1 v2 v3 v4
2 2 7 12 1
5 5 8 15 1
1 1 10 11 1
4 4 6 14 2
3 3 9 13 2
>x[order(x$v4,x$v2,decreasing=TRUE),] #按照降序排序
7. 总结数据信息(summarize the data)
> head(airquality,10) #head指定查看前6行,可以给定数字指定查看前几行。
> tail(airquality) #查看最后6行
> summary(airquality) #对数据的总体分布有一个清楚的总结
Ozone Solar.R Wind Temp
Min. : 1.00 Min. : 7.0 Min. : 1.700 Min. :56.00
1st Qu.: 18.00 1st Qu.:115.8 1st Qu.: 7.400 1st Qu.:72.00
Median : 31.50 Median :205.0 Median : 9.700 Median :79.00
Mean : 42.13 Mean :185.9 Mean : 9.958 Mean :77.88
3rd Qu.: 63.25 3rd Qu.:258.8 3rd Qu.:11.500 3rd Qu.:85.00
Max. :168.00 Max. :334.0 Max. :20.700 Max. :97.00
NA's :37 NA's :7
Month Day
Min. :5.000 Min. : 1.0
1st Qu.:6.000 1st Qu.: 8.0
Median :7.000 Median :16.0
Mean :6.993 Mean :15.8
3rd Qu.:8.000 3rd Qu.:23.0
Max. :9.000 Max. :31.0
> str(airquality) #以一种简洁的方式对数据进行总结
'data.frame': 153 obs. of 6 variables:
$ Ozone : int 41 36 12 18 NA 28 23 19 8 NA ...
$ Solar.R: int 190 118 149 313 NA NA 299 99 19 194 ...
$ Wind : num 7.4 8 12.6 11.5 14.3 14.9 8.6 13.8 20.1 8.6 ...
$ Temp : int 67 72 74 62 56 66 65 59 61 69 ...
$ Month : int 5 5 5 5 5 5 5 5 5 5 ...
$ Day : int 1 2 3 4 5 6 7 8 9 10 ...
> table(airquality$Month) #table函数对某列变量进行总结
5 6 7 8 9
31 30 31 31 30
>table(airquality$Ozone) #table函数默认忽略NA值
1 4 6 7 8 9 10 11 12 13 14 16 18 19 20 21 22 23 24
1 1 1 3 1 3 1 3 2 4 4 4 4 1 4 4 1 6 2
27 28 29 30 31 32 34 35 36 37 39 40 41 44 45 46 47 48 49
1 3 1 2 1 3 1 2 2 2 2 1 1 3 2 1 1 1 1
50 52 59 61 63 64 65 66 71 73 76 77 78 79 80 82 84 85 89
1 1 2 1 1 2 1 1 1 2 1 1 2 1 1 1 1 2 1
91 96 97 108 110 115 118 122 135 168
1 1 2 1 1 1 1 1 1 1
>table(airquality$Ozone,useNA="ifany") #给参数保留NA值
1 4 6 7 8 9 10 11 12 13 14 16 18 19 20
1 1 1 3 1 3 1 3 2 4 4 4 4 1 4
21 22 23 24 27 28 29 30 31 32 34 35 36 37 39
4 1 6 2 1 3 1 2 1 3 1 2 2 2 2
40 41 44 45 46 47 48 49 50 52 59 61 63 64 65
1 1 3 2 1 1 1 1 1 1 2 1 1 2 1
66 71 73 76 77 78 79 80 82 84 85 89 91 96 97
1 1 2 1 1 2 1 1 1 1 2 1 1 1 2
108 110 115 118 122 135 168 <NA>
1 1 1 1 1 1 1 37
> table(airquality$Month,airquality$Day)#table也可以同时看两列数据信息,形成一个行位月份,列为天数的矩阵
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
5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
6 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
9 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
28 29 30 31
5 1 1 1 1
6 1 1 1 0
7 1 1 1 1
8 1 1 1 1
9 1 1 1 0
>any(is.na(airquality$Ozone)) #统计一下数据airquality的Ozone列是否有缺失值
[1] TRUE
>sum(is.na(airquality$Ozone)) #统计一下缺失值的数量
[1] 37
>all(airquality$Month<12) #判断数据的月份是不是都小于12
[1] TRUE
##Titanic数据
> class(Titanic)
[1] "table"
>titanic=as.data.frame(Titanic)
>head(titanic)
Class Sex Age Survived Freq
1 1st Male Child No 0
2 2nd Male Child No 0
3 3rd Male Child No 35
4 Crew Male Child No 0
5 1st Female Child No 0
6 2nd Female Child No 0
>dim(titanic)
[1] 32 5
> summary(titanic)
Class Sex Age Survived Freq
1st :8 Male :16 Child:16 No :16 Min. : 0.00
2nd :8 Female:16 Adult:16 Yes:16 1st Qu.: 0.75
3rd :8 Median : 13.50
Crew:8 Mean : 68.78
3rd Qu.: 77.00
Max. :670.00
交叉表
交叉表用于查看两个变量的交叉信息
>x=xtabs(Freq ~ Class+Age, data=titanic) #查看class和age的交叉频率
> x
Age
Class Child Adult
1st 6 319
2nd 24 261
3rd 79 627
Crew 0 885
> class(x)
[1] "xtabs" "table"
>ftable(x) #内容与xtabs()一样,但是排版更加扁平了
> ftable(x)
Age Child Adult
Class
1st 6 319
2nd 24 261
3rd 79 627
Crew 0 885
查看数据大小
>object.size(airquality)
5632 bytes
>print(object.size(airquality),units="kb")
5.5 Kb