第5章工欲善其事、必先利其器
代码,是延伸我们思想最好的工具。
第6章基础编程——用别人的包和函数讲述自己的故事
6.1编程环境
1.R语言的三段论
大前提:计算机语言程序=算法+数据结构
小前提:R语言不过是计算机语言的一种
结论:R语言约等于基础编程+数据对象
2.运行机制
RStudio=记事本+R Console
6.2Mini案例
学生文理分科小案例(还有问题)
R仅有的命令形式是返回结果的函数和表达式
赋值是一种常见的操作:对象的读取、转换、模型的建立等
赋值给新的对象,往往也意味着数据的流转:读取、转换、探索、建模、评估等操作。
6.3站在巨人的肩膀上
1.编程的法则:
R编程=用别人的包和函数讲述自己的故事
2.如何搜索包
①上百度
②逛论坛,找答案,[r]搜索
https:///questions/tagged/r
③sos,扩展包,安装sos包,利用findFn()函数搜索包
④Task Views
⑤专注于某个领域,慢慢积累
3.利用好帮助文档,如?c
6.4控制流
结构化编程:任何简单或者复杂的逻辑都可以由顺序、分支和循环这三种基本结构组合而成。
1.顺序结构
> yw <- c(94,87,92,91,85,92) > sx <- c(82,94,79,84,92,82) > wy <- c(96,89,86,96,82,85) > ysw <- yw+sx+wy > ysw [1] 272 270 257 271 259 259 > (yw <- yw+2) > (mean_score <- mean(yw))#求语文平均分 [1] 92.16667 > sd(yw)#求语文成绩标准差 [1] 3.430258 > c(sd(yw),sd(sx),sd(wy)) [1] 3.430258 6.058052 5.865151 > show(yw) [1] 96 89 94 93 87 94 > show(sx)#显示数学成绩 [1] 82 94 79 84 92 82 > yw >= 90#向量化操作:逻辑判断 [1] TRUE FALSE TRUE TRUE FALSE TRUE > yw >= 85&sx >=85#向量化操作:逻辑判断 [1] FALSE TRUE FALSE FALSE TRUE FALSE > yw >=95 | sx >=95#向量化操作:逻辑判断 [1] TRUE FALSE FALSE FALSE FALSE FALSE
2.分支结构
条件表达式根据条件而执行不同的代码
if(条件){
cons.expr
}else{
alt.expr
}
注意:条件为一个标量的真或者假值,else子句如果存在的话,必须和}在同一行。else不能单起一行
> min_score <- min(yw)#语文最低成绩为87 if(min_score>=90){ message("语文成绩全部为优") //控制台输出 }else if(min_score>=80){ message("语文成绩至少为良") }else{ message("并非所有同学语文成绩均为优良") } > ifelse(yw >= 90,"优",ifelse(yw >= 88,"较好","一般")) [1] "优" "较好" "优" "优" "一般" "优"
3.循环结构 for while repeat
两种语句用于控制循环:
break 语句可以从当前运行的循环里面跳出来
next 语句会导致控制立即返回到循环的起点,next后面的语句不会被执行
实例:斐波那契数列
n_fib <- 16 fib <- numeric(n_fib) fib[1:2] <- c(1,1) for(i in 3:n_fib){ fib[i] <- fib[i-1]+fib[i-2] show(fib[i]) } fib > fib [1] 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
求1000以内的斐波那契数列:
#不知道循环多少次,仅知道终止条件,通过while来实现 fib <- c(1,1) while(sum(tail(fib,2))<1000){ fib <- c(fib,sum(tail(fib,2))) } fib
#也可以通过repeat来无条件循环,直到满足某个条件时break fib <- c(1,1) repeat{ //repeat==while(T) if(sum(tail(fib,2))>=1000){ break } fib <- c(fib,sum(tail(fib,2))) } fib
另一个例子:抽取幸运数字52
time_count <- 0 repeat{ my_number <- sample(100,1)#从1到100里面抽取一个数字 time_count <- time_count+1 if(my_number==52){ message("Hahaha,I finally got '52' after",time_count,"times") break }else { message(time_count,":Not lucky enough [",my_number, "]") } }
4.再说向量化:尽量不要使用显式循环,能向量化的运算的,尽量向量化,运算时间大大减少。
只要串行模式不是必须的,采用并行的方式。
R里面的并行作业:
向量化函数:sqrt(),sin(),round(),as.numeric(),cut(),weekdays(),+,-,*,/,&,|,%in%.....
6.5函数(1)
事不过三
1.编写函数
fun_name <- function(arg1,arg2=default1,...){ #注释 表达式(循环/判别/.....) return(返回值) }
ps:R里面一切都是对象,对象通过赋值来产生,函数也不例外。
函数声明关键字是function,function返回值就是函数
参数列表是以逗号分隔,函数主体可以是任何合法的R表达式
若无return语句,最后一个表达式的值作为返回值
以function_name(arg1,arg2,....)的形式调用函数
#摄氏度到华氏度的转换 ce2fa <- function(ce){#参数ce为输入 fa <- 1.8*ce+32#对输入进行处理 return(fa)#输出相应的值 } ce2fa(0)#0摄氏度相当于32华氏度 [1] 32 ce2fa(0:10) [1] 32.0 33.8 35.6 37.4 39.2 41.0 42.8 44.6 46.4 48.2 50.0
#注意位置参数和名义参数 frm <- function(name,frm="BUPT"){ cat(name,"is frm",frm) //显示 } frm("axb") axb is frm BUPT frm("axb","BJTU") //位置参数 axb is frm BJTU frm(frm="BJTU",name="axb")//名义参数 axb is frm BJTU
2.熟而不觉的函数:作为函数的二元操作符
+,-,*,/其实都是函数
%in%运算符:左侧的每个元素是否在右侧的集合之中
c(1,3,9) %in% 1:3 '%in%'(c(1,3,9),1:3) [1] TRUE TRUE FALSE #自己定义二元操作符函数:a,b为直角边,c为斜边 "%ab2c" <- function(a,b){ sqrt(sum(a^2,b^2)) } "%ab2c%"(3,4)
#看完%ab2c%之后,对下面的符号,也就觉得不过如此了 library(purrr) x <- c(17,28,17,12,15,12,49) x %>% unique() %>% #管道操作符也是一个二元操作符,函数而已 sort() [1] 12 15 17 28 49 #等价于下面的代码,不过是更加简洁优雅 x <- c(17,28,17,12,15,12,49) x2 <- unique(x) #剔除重复的数目 x3 <- sort(x2) x3 [1] 12 15 17 28 49 #定义二元操作符的时候,必须用双引号括起来 5+2 "+" <- function(x,y){ x*y } 5 + 2 [1] 10 rm("+")#消除恶作剧的+运算 5+2 [1] 7
ps:特殊函数的帮助文档
?“+” #双引号
?'+’#单引号
?·+·#反单引号
6.6函数(2)
1.不一样的plot
x <- seq(1,100,by=10) y <- 2*x+10 xy <- cbind(x,y) class(xy) #矩阵 [1] "matrix" "array" plot(xy, xlim = c(1,100), ylim = c(0,230), type = "o",col = "red" )
x <- seq(1,100,by=10) y <- 2*x+10 my_model <- lm(y~x) #拟合一个线性模型 class(my_model) #线性模型 [1] "lm" op <- par(mfrow=c(1,1)) plot(my_model) par(op)
多态的问题:针对不同的对象有不同的行为,泛型函数
2.泛型函数:见什么人说什么话,到什么山上唱什么歌
定义和调用的过程
#编写泛型函数 interface <- function(x,y){ #接口函数 message("Singal interface") UseMethod("particular",y)#参照第二个参数的类别来进行分发 } particular.classA <- function(x,y){#分发函数 message("Different behavior:classA") } particular.classB <- function(x,y){#分发函数 message("Different behavior:classB") } particular.default <- function(x,y){#分发函数 message("Different behavior:default") } x <- 1:10 y <- 1:20 class(y) <- "classA"#给A贴上标签-classA interface(x,y) Singal interface Different behavior:classA 类标签不一样的时候,接口是一样的 class(y) <- NULL interface(x,y) Singal interface Different behavior:default
重新审视+:
> methods("+") [1] +.Date +.glue* +.POSIXt +.vctrs_vctr* see '?methods' for accessing help and source code > library(ggplot2) > methods("+") [1] +.Date +.gg* +.glue* +.POSIXt [5] +.vctrs_vctr* see '?methods' for accessing help and source code
定义自己的+
"+.onlyFirst" <- function(a,b){ return(a[1]+b[1]) } a <- 1:5 a+6:10 1] 7 9 11 13 15 class(a) <- "onlyFirst"#给a贴上一个类标签onlyFirst a+6:10 [1] 7
3.递归:层层递进,逐层回归
老和尚讲故事:
rep(x, …):将vector x的值循环n遍
old_monk_story <- function(depth=1){ message(rep(" ",depth),"400 years ago(",2020-400*depth,"),monk[",depth,"]is telling the story:") if(2020-400*(depth+1)>=66){#据说佛教公元66年传入中国 old_monk_story(depth+1) } message(rep(" ",depth),"monk [",depth,"]finshed his story") } old_monk_story() 400 years ago(1620),monk[1]is telling the story: 400 years ago(1220),monk[2]is telling the story: 400 years ago(820),monk[3]is telling the story: 400 years ago(420),monk[4]is telling the story: monk [4]finshed his story monk [3]finshed his story monk [2]finshed his story monk [1]finshed his story
重新审视斐波那契数列
fib <- function(n){ if(n==1){ return(1) }else{ return(c(fib(n-1),sum(tail(fib(n-1),n=2)))) } } fib(10) [1] 1 1 2 3 5 8 13 21 34 55
错题整理:
1.对于特殊的函数if或者+等,通过helo()或是单引号、双引号、反单引号查找帮助文档
2.repeat循环体中必然有一条break语句,next语句只是中断本轮循环跳转至下一轮循环。若repeat语句中仅有next而无break,依然是死循环。
第7章数据对象——面向数据对象学习R语言
7.1向量与因子(1)
1.数据对象:
向量/因子
矩阵/数组
列表/数据框
2.创建向量
#创建向量最常见的方式c(),combine #字符型向量 xm <- c("周","xie","gao") Xb <- c("女","男","男") #数值型向量 yw <- c(94,92,98) #逻辑型向量 xb2 <- c(R,T,F) #不能有混合类型 my_pi <- c(3,".",1,4,1,5,9,2,6) my_pi [1] "3" "." "1" "4" "1" "5" "9" "2" "6" #材质不一样时强制转换 my_pi <- c(3,T,4,T,5,9,2,6) my_pi [1] 3 1 4 1 5 9 2 6 c(1,2,c(4,3),c(1,0))#不存在包含向量的向量,一律拆包 [1] 1 2 4 3 1 0 c(1,2,4,3,1,0 [1] 1 2 4 3 1 0
> (x1 <- vector("numeric",8))#事先知道长度和类型 ,默认值是0 [1] 0 0 0 0 0 0 0 0 > (x2 <- numeric(8)) [1] 0 0 0 0 0 0 0 0 > (x3 <- character(8)) [1] "" "" "" "" "" "" "" "" > (x4 <- vector(len=8)) [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE > (x5 <- logical(8)) [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
> #规则数列 > #等差数列 > seq(from=1,to=10,by=2) [1] 1 3 5 7 9 > seq(from=20,to=1,by=-2) [1] 20 18 16 14 12 10 8 6 4 2 > seq(from=1,to=20,length=10)#10个数,10个端点 [1] 1.000000 3.111111 5.222222 7.333333 9.444444 11.555556 [7] 13.666667 15.777778 17.888889 20.000000 > 1:10#创建from:10,步长为1的等差数列 [1] 1 2 3 4 5 6 7 8 9 10 > pi:1 [1] 3.141593 2.141593 1.141593 > #注意运算符的优先级 > 1:10-1#长度为10,:的优先级比-高 [1] 0 1 2 3 4 5 6 7 8 9 > 1:(10-1)#长度为9 [1] 1 2 3 4 5 6 7 8 9 > #不要有记忆的负担,在R里,不要吝啬()和{}的使用
创建向量:随机数列 > #产生随机数 > sample(10)#随机抽样 [1] 9 3 8 1 5 2 10 4 7 6 > sample(c("b","u","p","t","a","x","b"))#随机抽样 [1] "t" "a" "u" "b" "p" "x" "b" > set.seed(2012)#设定随机数种子,设定随机数结果固定的 > sample(10)#结果应该是一致的,reproduction research [1] 4 8 6 2 3 1 9 7 10 5 > (train_idx <- sample(1:10,7)) [1] 3 5 6 10 1 7 2
> #有放回的抽样 > re_sample <- sample(1:100,100,replace = T) > unique_re_sample <- unique(re_sample) #去掉重复的 > length(unique_re_sample)#有放回的抽样,有约36.8%的数不被抽 [1] 63
3.访问向量的子集,向量的下标,向量的子集通过[]来指定
第一种方法:采用1~n的正整数来指定,n为向量的长度
> yw <- c(94,87,92,91,85,92) > yw[c(2,5)] [1] 87 85 > yw[c(2,5)]-90 [1] -3 -5 > yw[c(2,5)] <- yw[c(2,5)]+6 > yw [1] 94 93 92 91 91 92
> yw[] <- mean(yw)#每一个元素都被赋值 > yw [1] 92.16667 > yw <- mean(yw) > yw [1] 92.16667 > > xm <- c("zhou","tang","xie","gao") > xm[c(1,3,3,2)] [1] "zhou" "xie" "xie" "tang" 子集不子,下标可重复,顺序可变
方法二:采用负整数,反向选出某些元素
> yw <- c(94,87,92,91,85,92) > yw[-c(2,5)] [1] 94 92 91 92 > which(yw<90) //输出的是下标 [1] 2 5 > idx <- which(yw<90) > yw[-idx]#避免了硬代码(可变的),增强了代码的可维护性 [1] 94 92 91 92
方法三:逻辑下标
> xm <- c("zhou","tang","shu","weng","qi","zhan") > yw <- c(94,87,92,91,85,92) > yw<90 [1] FALSE TRUE FALSE FALSE TRUE FALSE > yw[yw<90] [1] 87 85 > xm[yw<90] [1] "tang" "qi"
R为何智能的识别出了语文成绩小于90分(yw<90)的同学呢?
方法四:通过元素名称访问相应的子集
> xm <- c("zhou","tang","shu","weng","qi","zhan") > yw <- c(94,87,92,91,85,92) > names(yw) <- xm #取名 > yw zhou tang shu weng qi zhan 94 87 92 91 85 92 > yw[c("tang","qi")] tang qi 87 85
4.向量的基本操作
向量排序:
#向量排序 数值向量,默认从低到高,若想从高到低的话 fen_shu_xian2016 <- c(中科大=671,中央民族大学=625,北大=678,人大=670, 清华=680,北交=640,北京科技大=635,北京化工大=620,北邮=646,中农=634,北林=621) sort(fen_shu_xian2016) 北京化工大 北林 中央民族大学 中农 北京科技大 620 621 625 634 635 北交 北邮 人大 中科大 北大 640 646 670 671 678 清华 680 order(fen_shu_xian2016,decreasing = T) #返回的是下标 [1] 5 3 1 4 9 6 7 10 2 11 8 > fen_shu_xian2016[order(fen_shu_xian2016,decreasing = T)]#把下标交给 清华 北大 中科大 人大 北邮 680 678 671 670 646 北交 北京科技大 中农 中央民族大学 北林 640 635 634 625 621 北京化工大 620
向量逆序排序:
> yw <- c(94,87,92,91,85,92) > rev(yw) [1] 92 85 91 92 87 94 > yw[6]#可以用来取最后一个元素,但是这种硬代码很难维护 [1] 92 > yw[length(yw)]#基本可行的方法 [1] 92 > tail(yw,n=1)#更好的选择,推荐 [1] 92 > rev(tail(yw,n=3))#等价于head(rev(yw),n=3) [1] 92 85 91
数值向量运算:(从数学角度来看)
#原点 p0 <- c(x=0,y=0) #向量1 p1 <- c(x=1,y=2) #向量2 p2 <- c(x=2,y=3) #求和 p3 <- p1+p2 #数乘 p4 <- 1.5*p3 #内积:表示同心同向性 sum(p1*p2) > #向量的内积 > set.seed(2012)#括号内数值任意即可 > x <- rnorm(100)#生成随机数的数列,服从正太分布 > y <- rnorm(100) > #求向量的内积 > sum(x*y) [1] -11.1336 > sum(sort(x),sort(y)) [1] -20.56163 > sum(sort(x),sort(y,decreasing = T)) [1] -20.56163
7.2向量与因子(2)
1.变量分类
前两种无序因子和有序因子可以用因子来存储;
2.向量与因子的区别和联系:
向量用于存储数值变量(定距定比),因子用于存储类别变量(定类定序)
作为类别变量,只有有限个取值(类别),称为水平levels,取值水平往往远远少于观测对象(记录)的个数
在分组统计中,因子常用来作分组变量;分类问题均要求因变量为因子;在其他一些算法建模过程中,也要求其变量为因子(如arules::apriori())
因子也是也是更有效的存储方式:存储为整型向量,只不过每一个1~levels的正整数代表了相应的类别
3.因子的创建
方法一:基于向量
> xb <- c("女","男","男","女","男","女") > xb [1] "女" "男" "男" "女" "男" "女" > typeof(xb) [1] "character" > xb <- factor(xb) > xb <- factor(xb) > xb [1] 女 男 男 女 男 女 Levels: 男 女因子的基本操作
> xb[-c(2:3,6)] [1] 女 女 男 Levels: 男 女 > xb[1] <- "男" > xb [1] 男 男 男 女 男 女 Levels: 男 女 > xb=="男" [1] TRUE TRUE TRUE FALSE TRUE FALSE > nlevels(xb)#取值水平的个数 [1] 2 > levels(xb)#取值水平 [1] "男" "女" > typeof(xb) [1] "integer"#内部实际存储为一个整型的向量 > as.numeric(xb) [1] 1 1 1 2 1 2 > as.character(xb) [1] "男" "男" "男" "女" "男" "女"
对于因子而言,表面上看是字符,实际上在内存里面是一个整型的向量。
> number_factors <- factor(c(10,20,20,20,10)) > mean(number_factors) [1] NA 表面上看只是字符 > as.numeric(number_factors)#使用数值向量进行创建的时候,“10”当成字符来看待 [1] 1 2 2 2 1 > mean(as.numeric(number_factors)) [1] 1.6 > mean(as.numeric(as.character(number_factors))) [1] 16 > mean(as.numeric(levels(number_factors)[number_factors])) [1] 16
> #有序因子 > score <- factor(c("优","良","优","优","良","优"),ordered = T) > score[1]>score[2]#怎么识别出来的呢? [1] TRUE > days <- factor(c("周一","周三","周二","周二"),ordered = T) > days[3]<days[2] [1] TRUE > days[1]<days[2] [1] FALSE > days [1] 周一 周三 周二 周二 Levels: 周二 < 周三 < 周一 #其实并没有那么智能,只是内部编码问题而已,按照字母顺序
#规定好levels,给定顺序 > days <- factor(c("周一","周三","周二","周二"),ordered = T,levels = c("周一","周二","周三")) > days [1] 周一 周三 周二 周二 Levels: 周一 < 周二 < 周三 > days[1]<days[3] [1] TRUE
方法二:基于数值变量使用cut()进行分箱,进行离散化处理。
> #实战才是王道:数据分箱 > #百分制成绩变为五分制成绩 > yw <- c(94,87,92,91,85,92) > #数据分箱 > yw5 <- cut(yw,breaks=c(0,(6:10)*10))#挖坑的过程,后面0,60,70,80,90,100这几个端点 > yw5 [1] (90,100] (80,90] (90,100] (90,100] (80,90] (90,100] Levels: (0,60] (60,70] (70,80] (80,90] (90,100] #左开右闭,0没有取到 改进: > #数据分箱+闭区间 > yw5 <- cut(yw,breaks=c(0,(6:10)*10),include.lowest = T)#挖坑的过程,后面0,60,70,80,90,100这几个端点 > yw5 [1] (90,100] (80,90] (90,100] (90,100] (80,90] (90,100] Levels: [0,60] (60,70] (70,80] (80,90] (90,100] 问题:60划分区间不对 > #数据分箱+闭区间+左闭右开 > yw5 <- cut(yw,breaks=c(0,(6:10)*10),include.lowest = T,right=F) > yw5 [1] [90,100] [80,90) [90,100] [90,100] [80,90) [90,100] Levels: [0,60) [60,70) [70,80) [80,90) [90,100] 进一步改进: > #数据分箱+闭区间+左闭右开+有序因子 > yw5 <- cut(yw,breaks=c(0,(6:10)*10),include.lowest = T,right=F,ordered_result = T) > yw5 [1] [90,100] [80,90) [90,100] [90,100] [80,90) [90,100] Levels: [0,60) < [60,70) < [70,80) < [80,90) < [90,100] > #数据分箱+闭区间+左闭右开+有序因子+标签 > yw5 <- cut(yw,breaks=c(0,(6:10)*10),include.lowest = T,right=F,ordered_result = T, + labels = c("不及格","及格","中","良","优")) > yw5 [1] 优 良 优 优 良 优 Levels: 不及格 < 及格 < 中 < 良 < 优
7.3矩阵与数组(1)
1.矩阵的创建:
#单变量观测值可以用向量或因子存储 #假设对观测对象的多个属性同时进行记录(多变量) #若这些向量是同质的,宜采用矩阵作为一个整体进行存储 #依然以学生成绩这份数据为例 xm <- c("周莉","唐海明","舒江辉","翁可","奇强","詹蓉") yw <- c(94,87,92,91,85,92) sx <- c(82,94,79,84,92,82) wy <- c(96,89,86,96,82,85) #语文、数学、外语三科成绩作为一个整体 ysw <- matrix(c(94,87,92,91,85,92, 82,94,79,84,92,82, 96,89,86,96,82,85),ncol = 3)#分成3列,长度为18的数值向量 #矩阵在创建的时候案列优先进行填充 colnames(ysw) <- c("yw","sx","wy") row.names(ysw) <- xm#给行或者列命名 View(ysw)
#假设数据本身就是站着的 ysw <- matrix( c(94,82,96, 87,94,89, 92,79,86, 91,84,96, 85,92,82, 92,82,85), byrow = TRUE,#注意byrow=参数的设置,默认是F ncol = 3) colnames(ysw) <- c("yw","sx","wy") row.names(ysw) <- xm View(ysw)
矩阵的基本性质:
> colnames(ysw) [1] "yw" "sx" "wy" > row.names(ysw) [1] "周莉" "唐海明" "舒江辉" "翁可" "奇强" "詹蓉" > nrow(ysw)#行数 [1] 6 > ncol(ysw)#列数 [1] 3 > dim(ysw)#行数和列数 [1] 6 3 > dimnames(ysw)#行列名称 [[1]] [1] "周莉" "唐海明" "舒江辉" "翁可" "奇强" "詹蓉" [[2]] [1] "yw" "sx" "wy"
#子集的访问仍然是通过[] #由于矩阵是二维的,需要','来分别指定行和列 ysw[1,]#第一个同学语文、数学、外语得分 ysw["周莉",]#同上 yw sx wy 94 82 96 ysw[,1]#语文成绩 ysw[,"yw"]#同上 周莉 唐海明 舒江辉 翁可 奇强 詹蓉 94 87 92 91 85 92 > ysw["周莉",2:3] sx wy 82 96 > ysw[1,c("sx","wy")] sx wy 82 96 > ysw[1,-1] sx wy 82 96
行列重排:
> #列重新排序 > ysw[,c("sx","yw","wy")] sx yw wy 周莉 82 94 96 唐海明 94 87 89 舒江辉 79 92 86 翁可 84 91 96 奇强 92 85 82 詹蓉 82 92 85 > ysw[,c(2,1,3)] sx yw wy 周莉 82 94 96 唐海明 94 87 89 舒江辉 79 92 86 翁可 84 91 96 奇强 92 85 82 詹蓉 82 92 85
> #行进行排序:按照数学成绩进行排序 > (order_sx <- order(ysw[,"sx"],decreasing = T)) [1] 2 5 4 1 6 3 > ysw[order_sx,] yw sx wy 唐海明 87 94 89 奇强 85 92 82 翁可 91 84 96 周莉 94 82 96 詹蓉 92 82 85 舒江辉 92 79 86
#矩阵合并 #观测到新的记录 ysw1 <- matrix(c(94,87,92,91,85,92, 82,94,79,84,92,82, 96,89,86,96,82,85),ncol = 3, dimnames = list( c("周莉","唐海明","舒江辉","翁可","奇强","詹蓉"), c("yw","sx","wy") )) ysw2 <- matrix( c(88,81,72,89,86,87), ncol = 3, dimnames = list( c("穆伶俐","易伟杰"), c("yw","sx","wy") ) ) #叠罗汉一样 ysw <- rbind(ysw1,ysw2) View(ysw)
#新增列 zzls <- matrix( c(97,97, 95,94, 98,95, 93,97, 93,87, 91,90, 94,87, 97,94), ncol = 2,byrow = T, dimnames = list( c("周莉","唐海明","舒江辉","翁可","奇强","詹蓉","穆伶俐","易伟杰"), c("zz","ls") ) ) cjb <- cbind(ysw,zzls)#按列进行合并 View(cjb)
其他一些基本操作:
> rowSums(cjb)#每个同学的总成绩 周莉 唐海明 舒江辉 翁可 奇强 詹蓉 穆伶俐 易伟杰 466 459 450 461 439 440 427 448 > colMeans(cjb)#按列求平均值,每门课的平均分 yw sx wy zz ls 88.750 84.250 88.375 94.750 92.625 > #更一般的方法 > apply(cjb,1,sum)#第二个参数表示作用的要么是行,要么是列 周莉 唐海明 舒江辉 翁可 奇强 詹蓉 穆伶俐 易伟杰 466 459 450 461 439 440 427 448 > apply(cjb,2,mean) yw sx wy zz ls 88.750 84.250 88.375 94.750 92.625 > round(apply(cjb,2,sd),digits = 2)#sd标准差 yw sx wy zz ls 4.33 7.23 5.10 2.43 4.10
> #可以自定义函数 > coefficient_of_variation <- function(x){ + sd(x)/mean(x) + + } > apply(cjb,2,coefficient_of_variation) yw sx wy zz ls 0.04883661 0.08576790 0.05767772 0.02569779 0.04430305 > #当然,也可以采用匿名函数 > apply(cjb, 2, function(x){ + sd(x)/mean(x) + }) yw sx wy zz ls 0.04883661 0.08576790 0.05767772 0.02569779 0.04430305
总结:apply代表了一种数据处理模式
split-apply-combine模式,先分组,然后对每一个组进行操作,然后将操作结果进行combine在一起
apply函数族,以及tidyverse包
7.4矩阵和数组(2)
1.矩阵的运算,可以通过solve(A,b)
解以下方程组:
#定义系数矩阵 A <- matrix( c(1,2,3, 2,2,5, 3,5,1), ncol = 3, byrow = T#按行排列 ) b <- 1:3 solve(A,b) [1] 1 0 0
> #可以利用solve函数求逆矩阵 > diag(3)#生成单位矩阵 [,1] [,2] [,3] [1,] 1 0 0 [2,] 0 1 0 [3,] 0 0 1 > solve(A,diag(3)) [,1] [,2] [,3] [1,] -1.5333333 0.86666667 0.26666667 [2,] 0.8666667 -0.53333333 0.06666667 [3,] 0.2666667 0.06666667 -0.13333333 > solve(A)#默认b是单位矩阵 [,1] [,2] [,3] [1,] -1.5333333 0.86666667 0.26666667 [2,] 0.8666667 -0.53333333 0.06666667 [3,] 0.2666667 0.06666667 -0.13333333 > solve(A) %*% A #A的逆乘以A [,1] [,2] [,3] [1,] 1.000000e+00 8.881784e-16 1.054712e-15 [2,] -4.440892e-16 1.000000e+00 -7.077672e-16 [3,] -5.551115e-17 -1.110223e-16 1.000000e+00 > sqrt(2)^2==2 [1] FALSE #以上两个例子原因都是一样的,涉及到R存储的有限位数,根号2是一个无理数,有无限位,但在存储的时候只能存储一部分,所以并不是完全等于2 > dplyr::near(sqrt(2)^2,2)#dplyer是一个包 [1] TRUE > all(dplyr::near(solve(A) %*% A,diag(3))) [1] TRUE
2.数组
数组是矩阵的扩展,矩阵是二位数组,以图像处理为例,简述三维数组的操作。
#数组 #读入一个彩色jpg文件,在R里面就是一个数组 > jpg_url <- "https://raw./byaxb/RDataAnalytics/master/data/presidents.jpg" > download.file(jpg_url,"presidents.jpg",mode = "wb") 试开URL’https://raw./byaxb/RDataAnalytics/master/data/presidents.jpg' Error in download.file(jpg_url, "presidents.jpg", mode = "wb") : 无法打开URL'https://raw./byaxb/RDataAnalytics/master/data/presidents.jpg' 此外: Warning message: In download.file(jpg_url, "presidents.jpg", mode = "wb") : InternetOpenUrl失败:’无法与服务器建立连接' > library(imager) 载入需要的程辑包:magrittr 载入程辑包:'imager’ The following object is masked from 'package:magrittr’: add The following objects are masked from 'package:stats’: convolve, spectrum The following object is masked from 'package:graphics’: frame The following object is masked from 'package:base’: save.image > presidents <- load.image("presidents.jpg") Error in wrap.url(file, load.image.internal) : File not found > str(presidents) 'cimg' num [1:482, 1:345, 1, 1:3] 0.984 0.961 0.918 0.902 0.902 ...#z轴3个二维数组
#图像与数组,将第2,3个图层赋值为0 presidents[,,2] <- 0 presidents[,,3] <- 0 plot(presidents)
#只看绿色图层 presidents[,,1] <- 0 presidents[,,3] <- 0 plot(presidents)
#调色,都是对数组的操作 #黄色 presidents[,,3] <- 0 plot(presidents)
#加上马赛克,加一个噪声模糊处理 area_coor_x <- 350:449#100 area_coor_y <- 110:259#150 array_dim <- c(length(area_coor_x),length(area_coor_y),3) array_data <- runif(prod(array_dim))#prod()表示相乘生成噪声,runif()表示均匀分布 randow_noise <- array(dim = array_dim,data = array_data) presidents[area_coor_x,area_coor_y,] <- (1-0.6)*presidents[area_coor_x,area_coor_y,]+ 0.6*randow_noise plot(presidents)
7.5列表与数据框(1)
定义:列表是对象的有序集合,包含的对象又称为它的分量
列表是最为灵活,最具有包容性
对所包含的对象没有限制,可以是不同的类型、不同的长度
> #北京邮电大学下设以下学院 > xue_yuan <- c("信息与通信学院","电子工程学院","计算机学院","自动化学院","软件学院","数字媒体与设计艺术学院","现代邮政学院","网络空间安全学院","光电信息学院","理学院","经济管理学院", + "马克思主义学院","国际学院","网络教育学院","继续教育学院","民族教育学院") > #拥有以下基地 > ji_di <- c(国家重点实验室=2,国家工程实验室=2,部级实验室=9) > xiao_qu <- c("西土城路校区","沙河校区","宏福校区")#校区分布 > xue_sheng <- c(全日制=30000,非全日制=4500)#学生数量 > #变成一个整体,集合在一起 > bupt <- list(xue_yuan=xue_yuan, + xiao_qu=xiao_qu, + ji_di=ji_di, + xue_sheng=xue_sheng) > #查看一些属性 > length(bupt) [1] 4 > names(bupt) [1] "xue_yuan" "xiao_qu" "ji_di" "xue_sheng" > typeof(bupt) [1] "list"
一些基本操作
> #访问列表子集¥ > bupt$xue_sheng 全日制 非全日制 30000 4500 > bupt$xue_sheng["全日制"] 全日制 30000 > sum(bupt$xue_sheng) [1] 34500 > #通过[]来访问子集 > bupt[4]#提取的还是列表的形式 $xue_sheng 全日制 非全日制 30000 4500 > typeof(bupt[4])#单个[]看到的依然是包装箱 [1] "list" > bupt[[4]] #双层[]才进入包装箱内部,看到组成部分 全日制 非全日制 30000 4500 > typeof(bupt[[4]]) [1] "double" > sum(bupt[4]) Error in sum(bupt[4]) : 'type'(list)参数不对 > sum(bupt[[4]])#正确的打开方式 [1] 34500 > bupt["xue_sheng"] $xue_sheng 全日制 非全日制 30000 4500 ———————————————————————————————————————————————————————————————————————————————————— > bupt[["bupt"]] NULL > sum(bupt[4]) Error in sum(bupt[4]) : 'type'(list)参数不对 > sum(bupt[[4]])#正确的打开方式 [1] 34500 > bupt["xue_sheng"] $xue_sheng 全日制 非全日制 30000 4500 > bupt[["xue_sheng"]] 全日制 非全日制 30000 4500
总结:一下三种方式效果相同
bupt$xue_sheng bupt[[4]] bupt[["xue_sheng"]] 全日制 非全日制 30000 4500
增、删、改、查
> #增加一类,直接赋值 > bupt$A_xueke <- c("信息与通信工程","计算机科学与技术","电子科学与技术") > length(bupt) [1] 5 > names(bupt) [1] "xue_yuan" "xiao_qu" "ji_di" "xue_sheng" "A_xueke" > bupt$A_xueke <- NULL#注意NULL/NA/""的区别 > names(bupt) [1] "xue_yuan" "xiao_qu" "ji_di" "xue_sheng"
列表操作:
#队列表的每一个组成部分,执行某种操作 > (component_length <- lapply(bupt, length)) $xue_yuan [1] 16 $xiao_qu [1] 3 $ji_di [1] 3 $xue_sheng [1] 2 > unlist(component_length)#拉平,变成带名称的数值向量 xue_yuan xiao_qu ji_di xue_sheng 16 3 3 2 > sapply(bupt,length) xue_yuan xiao_qu ji_di xue_sheng 16 3 3 2 > sapply(bupt,typeof) xue_yuan xiao_qu ji_di xue_sheng "character" "character" "double" "double"
7.6列表和数据框(2)
1.数据整理最后都是为了得到数据框
2.数据框的组成:
数据框是最美好的数据对象
形式上是矩阵,本质上是列表
与数据库关系表、Excel中的sheet相似
个体-变量矩阵
列:变量、属性、特征、维度
行:记录、观测值、n维数据空间的一个点
3.创建数据框
xm <- c("周莉","唐海明","舒江辉","翁可","奇强","詹蓉") xb <- factor(c("女","男","男","女","男","女")) yw <- c(94,87,92,91,85,92) sx <- c(82,94,79,84,92,82) wy <- c(96,89,86,96,82,85) cjb <- data.frame(xm=xm,#非同质,和列表类似 xb=xb, yw=yw, sx=sx, wy=wy) cjb xm xb yw sx wy 1 周莉 女 94 82 96 2 唐海明 男 87 94 89 3 舒江辉 男 92 79 86 4 翁可 女 91 84 96 5 奇强 男 85 92 82 6 詹蓉 女 92 82 85
4.数据框的基本操作
#由于数据框本质上是列表,可以通过以下三种方式访问其中的列 cjb$xm cjb[[1]] cjb[["xm"]] [1] "周莉" "唐海明" "舒江辉" "翁可" "奇强" "詹蓉" #一般来说[[]]的用法较少,要么采用$,要么采用以下的矩阵式操作,逗号前面是行,后面是列 cjb[,1] cjb[,"xm"] > cjb[1,] xm xb yw sx wy 1 周莉 女 94 82 96 > cjb[c(1,3),c("xm","sx")] xm sx 1 周莉 82 3 舒江辉 79 > cjb[1:3,-1] xb yw sx wy 1 女 94 82 96 2 男 87 94 89 3 男 92 79 86
#作为列表,通过美元符号增加一列政治zz cjb$zz <- c(97,95,98,93,93,91) #像矩阵,cbind也可以 cjb <- cbind(cjb,ls=c(97,94,95,97,87,90)) View(cjb)
5.读取数据
#数据不会再代码里逐字敲入,也不会通过控制台输入 #而是直接读取已经采集好的数据 cjb_url <- "https://github.com/byaxb/RDataAnalytics/raw/master/data/cjb.csv" cjb <- read.csv(cjb_url,header = T,stringsAsFactors = F) View(cjb)
head(cjb)#默认显示前6行 tail(cjb,n=3)#默认后6行 > #查看数据的结构 > #Compactly Display the Structure > str(cjb) 'data.frame':775 obs. of 13 variables: $ xm : chr "周黎" "汤海明" "舒江辉" "翁柯" ... $ bj : int 1101 1101 1101 1101 1101 1101 1101 1101 1101 1101 ... $ xb : chr "女" "男" "男" "女" ... $ yw : int 94 87 92 91 85 92 88 81 88 94 ... $ sx : int 82 94 79 84 92 82 72 89 77 81 ... $ wy : int 96 89 86 96 82 85 86 87 95 88 ... $ zz : int 97 95 98 93 93 91 94 97 94 91 ... $ ls : int 97 94 95 97 87 90 87 94 84 85 ... $ dl : int 98 94 96 94 88 92 88 96 94 98 ... $ wl : int 95 90 89 82 95 82 89 81 87 81 ... $ hx : int 94 90 94 90 94 98 98 88 94 88 ... $ sw : int 88 89 87 83 93 90 94 83 82 88 ... $ wlfk: chr "文科" "文科" "文科" "文科" ...
> summary(cjb)#对数据进行统计描述 xm bj xb yw sx Length:775 Min. :1101 Length:775 Min. : 0.00 Min. : 0.00 Class :character 1st Qu.:1104 Class :character 1st Qu.:85.00 1st Qu.: 81.00 Mode :character Median :1107 Mode :character Median :88.00 Median : 89.00 Mean :1108 Mean :87.27 Mean : 86.08 3rd Qu.:1111 3rd Qu.:91.00 3rd Qu.: 95.00 Max. :1115 Max. :96.00 Max. :100.00 wy zz ls dl wl Min. : 0.0 Min. : 0.00 Min. : 0.00 Min. : 0.00 Min. : 0.0 1st Qu.:84.0 1st Qu.: 90.00 1st Qu.: 85.00 1st Qu.: 90.00 1st Qu.: 74.0 Median :88.0 Median : 93.00 Median : 90.00 Median : 94.00 Median : 83.0 Mean :87.4 Mean : 92.21 Mean : 89.03 Mean : 92.91 Mean : 81.1 3rd Qu.:92.0 3rd Qu.: 95.00 3rd Qu.: 94.50 3rd Qu.: 96.00 3rd Qu.: 91.0 Max. :99.0 Max. :100.00 Max. :100.00 Max. :100.00 Max. :100.0 hx sw wlfk Min. : 0.00 Min. : 0.00 Length:775 1st Qu.: 88.00 1st Qu.: 81.00 Class :character Median : 94.00 Median : 88.00 Mode :character Mean : 91.57 Mean : 86.26 3rd Qu.: 98.00 3rd Qu.: 93.00 Max. :100.00 Max. :100.00
> #查看数据 > names(cjb) [1] "xm" "bj" "xb" "yw" "sx" "wy" "zz" "ls" "dl" "wl" "hx" "sw" [13] "wlfk" > colnames(cjb)#结果同上 > nrow(cjb) [1] 775 > ncol(cjb) [1] 13 > length(cjb)#结果同上 #作必要的类型转换 cjb$bj <- factor(cjb$bj) cjb$xb <- factor(cjb$xb) cjb$wlfk <- factor(cjb$wlfk) str(cjb) summary(cjb)#再次summary,数据分析总是反复迭代的 结果对比如图所示:
6.数据框记录排序
#数据框记录排序 cjb$zcj <- apply(cjb[,4:12],1,sum)#每个同学的9门课总成绩 order(cjb$zcj,decreasing = T)[1:5]#取到下标 cjb_sorted <- cjb[order(cjb$zcj,decreasing = T),] View(cjb_sorted)
建模一般分为数据集合测试集
#数据集分为训练集和测试集 set.seed(2012)#设定随机数的种子 n_record <- nrow(cjb) train_idx <- sample(1:n_record,floor(n_record*0.7))#选出70%个数量,floor向下取整,ceiling向上取整 train_idx <- sample(n_record,n_record*0.7)#简写 length(train_idx) [1] 542 test_idx <- (1:n_record)[-train_idx] test_idx <- setdiff(1:n_record,train_idx)#效果同上一个语句 length(test_idx) [1] 233 #得到测试集和训练集 train_set <- cjb[train_idx,] test_set <- cjb[-train_idx,] test_set <- cjb[test_idx,] #显然,下面这种方式是错误的 train_set <- cjb[sample(n_record,n_record*0.7),] test_set <- cjb[sample(n_record,n_record*0.3),]#测试集和训练集可能交集非空 #在工业级/商业集应用中,建议不要重复造轮子,直接采用caret等包中训练集和测试集划分 相关函数如createDataPartition()
错题整理:
①访问向量时候,正整数、负整数都可以作为下标,但是不能混用
②语句1:10-1:3的结果是0003336669
在进行向量化运算时,若长度不等,则采用循环补齐的方式进行,相当于1:10-c(1:3,1:3,1)
③sort()函数默认对值进行从低到高排序
④order()排序是先进行强制类型转换,然后按照从低到高的顺序取下标
⑤定序变量,有高下优劣之分,但不能比较差别,例如表征规模、等级的变量
⑥若字符向量partA是列表my_list的第1个组成部分,那么my_list[1]的结果是列表对象,单个[]依旧是列表,[[]]才是组成部分本身,语句my_list$partA与my_list[[1]]和my_list[['partA']]等价
第8章人人都爱tidyverse
tidy整洁的 verse诗篇
tidyverse扩展包,编程理念、风格
library(tidyverse)
-- Attaching packages --------------------------------------- tidyverse 1.3.0 --
√ ggplot2 3.3.2 √ purrr 0.3.4
√ tibble 3.0.3 √ dplyr 1.0.2√ tidyr 1.1.2 √ stringr 1.4.0
√ readr 1.3.1 √ forcats 0.5.0-- Conflicts ------------------------------------------ tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()x dplyr::lag() masks stats::lag()
tidyverse扩展包套装:
序号 | 扩展包 | 功能 |
1 |
ggplot2 |
data visualisation |
2 |
dplyr |
data manipulation |
3 |
tidyr |
data tidying |
4 |
readr |
data import |
5 |
purrr |
functional programming |
6 |
tibble |
tibbles,a modern re-imaging of data frames |
7 |
stringr |
strings |
8 |
forcats |
for Categorical Variables(Factors) |
重点讲dplyr这个包:
1.管道操作符%>%,二元操作符
lhs(value)%>%rhs(function)
表达式 | 用法 |
x %>%f |
f(x) |
x %>% f(y) |
f(x,y) |
y %>% f(x, .)#前面的值y不是第一个参数 |
f(x,y) |
z %>% f(x,y,arg=.) |
f(x,y,arg=z) |
x %>% f %>% g %>%h |
h(g(f(x))) |
#查看数据记录 cjb %>%head xm bj xb yw sx wy zz ls dl wl hx sw wlfk zcj 1 周黎 1101 女 94 82 96 97 97 98 95 94 88 文科 841 2 汤海明 1101 男 87 94 89 95 94 94 90 90 89 文科 822 3 舒江辉 1101 男 92 79 86 98 95 96 89 94 87 文科 816 4 翁柯 1101 女 91 84 96 93 97 94 82 90 83 文科 810 5 祁强 1101 男 85 92 82 93 87 88 95 94 93 文科 809 6 湛容 1101 女 92 82 85 91 90 92 82 98 90 文科 802 cjb%>%head(n=4)#查看前四行,下面这两个语句完全等价 head(cjb,n=4) xm bj xb yw sx wy zz ls dl wl hx sw wlfk zcj 1 周黎 1101 女 94 82 96 97 97 98 95 94 88 文科 841 2 汤海明 1101 男 87 94 89 95 94 94 90 90 89 文科 822 3 舒江辉 1101 男 92 79 86 98 95 96 89 94 87 文科 816 4 翁柯 1101 女 91 84 96 93 97 94 82 90 83 文科 810
2.dplyr:data manipulation
序号 | 扩展包 | 功能 |
1 |
select() |
选择某些列 |
2 |
mutate() |
对某些列进行增加或者修改 |
3 |
filter() |
针对行,选择某些行 |
4 |
arrange() |
排序 |
5 |
summarise() |
汇总 |
#选择列 cjb %>%select(xm,yw,sx) %>% head(n=3)#管道化的连续操作 xm yw sx 1 周黎 94 82 2 汤海明 87 94 3 舒江辉 92 79 cjb %>%select(xm,yw,sx) %>% set_names(c("姓名","语文","数学")) %>% head(n=3) 姓名 语文 数学 1 周黎 94 82 2 汤海明 87 94 3 舒江辉 92 79 > cjb %>% select(1,4:12) %>% head(n=3) xm yw sx wy zz ls dl wl hx sw 1 周黎 94 82 96 97 97 98 95 94 88 2 汤海明 87 94 89 95 94 94 90 90 89 3 舒江辉 92 79 86 98 95 96 89 94 87 > cjb %>% select(xm,yw:sw) %>% head(n=3) xm yw sx wy zz ls dl wl hx sw 1 周黎 94 82 96 97 97 98 95 94 88 2 汤海明 87 94 89 95 94 94 90 90 89 3 舒江辉 92 79 86 98 95 96 89 94 87
> #列的修改 > cjb %>% mutate_at(vars(bj,xb,wlfk),factor) %>% #强制转换为因子 + mutate(zcj=rowSums(.[4:12])) %>% + arrange(desc(zcj)) %>% #从高到低排序 + tail(n=2) xm bj xb yw sx wy zz ls dl wl hx sw wlfk zcj 774 滑亚 1113 男 33 46 30 65 82 76 56 76 59 理科 523 775 张良平 1115 男 0 0 0 0 0 0 0 0 0 理科 0 #成绩表本身并没有该表,生成了一个临时的数据对象 #让更改生效,采用%<>%操作符 cjb %<>% mutate_at(vars(bj,xb,wlfk),factor) %>% #强制转换为因子 mutate(zcj=rowSums(.[4:12])) %>% arrange(desc(zcj)) #从高到低排序 View(cjb) #和上述语句等价 cjb <- cjb %>% mutate_at(vars(bj,xb,wlfk),factor) %>% #强制转换为因子 mutate(zcj=rowSums(.[4:12])) %>% arrange(desc(zcj)) #从高到低排序
#选择行 cjb %>%filter(yw<60) xm bj xb yw sx wy zz ls dl wl hx sw wlfk zcj 1 滑亚 1113 男 33 46 30 65 82 76 56 76 59 理科 523 2 张良平 1115 男 0 0 0 0 0 0 0 0 0 理科 0 > #只要有不及格的成绩就把这个同学找出来 > cjb %>% filter_at(vars(4:12),any_vars(.<60)) xm bj xb yw sx wy zz ls dl wl hx sw wlfk zcj 1 陈锡生 1107 男 91 89 75 95 100 100 59 86 85 文科 780 2 凌诗雨 1101 女 84 55 95 90 86 100 80 96 86 文科 772 ......... #分组统计,有分组变量也有目标变量 cjb %>% filter(zcj!=0) %>% group_by(xb) %>% summarise(count=n(), max=max(zcj), mean=mean(zcj), min=min(zcj)) # A tibble: 2 x 5 xb count max mean min <fct> <int> <dbl> <dbl> <dbl> 1 男 368 885 793. 523 2 女 406 879 797. 647
#tidyr:长宽变换,Key是分组变量,value是目标变量 cjb %>%gather(key = ke_mu,value = cheng_ji,yw:sw) %>% arrange(xm) xm bj xb wlfk zcj ke_mu cheng_ji 1 艾春莲 1103 女 文科 713 yw 86 2 艾春莲 1103 女 文科 713 sx 59 3 艾春莲 1103 女 文科 713 wy 87 4 艾春莲 1103 女 文科 713 zz 89 5 艾春莲 1103 女 文科 713 ls 85 6 艾春莲 1103 女 文科 713 dl 92 7 艾春莲 1103 女 文科 713 wl 73 8 艾春莲 1103 女 文科 713 hx 74 9 艾春莲 1103 女 文科 713 sw 68 10 艾阳芳芳 1112 女 理科 820 yw 89 11 艾阳芳芳 1112 女 理科 820 sx 98 12 艾阳芳芳 1112 女 理科 820 wy 91 13 艾阳芳芳 1112 女 理科 820 zz 95 14 艾阳芳芳 1112 女 理科 820 ls 87 15 艾阳芳芳 1112 女 理科 820 dl 94 16 艾阳芳芳 1112 女 理科 820 wl 91 17 艾阳芳芳 1112 女 理科 820 hx 86 18 艾阳芳芳 1112 女 理科 820 sw 89 ....... #按科目进行汇总统计 cjb %>% filter(zcj!=0) %>% gather(key = ke_mu,value = cheng_ji,yw:sw) %>% group_by(ke_mu) %>% summarise(max=max(cheng_ji), mean=mean(cheng_ji), median=median(cheng_ji), min=min(cheng_ji)) %>% arrange(desc(mean)) # A tibble: 9 x 5 ke_mu max mean median min <chr> <int> <dbl> <dbl> <int> 1 dl 100 93.0 94 70 2 zz 100 92.3 93 65 3 hx 100 91.7 94 52 4 ls 100 89.1 90 0 5 wy 99 87.5 88 30 6 yw 96 87.4 88 33 7 sw 100 86.4 88 55 8 sx 100 86.2 89 26 9 wl 100 81.2 83 21
错题:①函数n()表示计算本组记录数
第9章最美不过数据框
1.发现数据框背后的规律
数据框(关系表)是最常见的数据对象
发现数据背后的规律
很大程度上就是,发现数据框背后的规律
以机器学习为内核:
数据分析=(约等于)机器学习/数据挖掘
=认识数据+关联+分类+聚类
=寻找关系结构(核心是归类)
2.数据框里有乾坤
分类本质就是函数的映射(按照一定的法则),有监督的学习
数据框里的函数(函数的表示法:列表法)
数据框:函数三种表现形式之一——列表法
一定的法则在数据框中的体现:x和y出现在同一行之中(只是没那么严格)
3.数据框与数据空间
数据集包含n个属性/特征,张成一个n维数据空间
距离关系的远近,在数据空间中形成了自然的结构:簇
无监督的方法:聚类
数据框中列表示维度,行表示点
4.数据框里的关联规则
关联规则A蕴含B:A发生时伴随着B发生
支持度:support(A=》B)=P(A U B)
置信度:confident(A=》B)=P(B|A)=P(A U B)/P(A)
关系表:data.frame|tibble|data.table
一切都是关系结构:关系表几乎可以上升为一个数学概念
题目:① 数据框中的列,从数据库角度讲,是字段;从统计的角度讲,是变量;从机器学习的角度讲,是属性、特征;从数据空间的角度讲,是空间的维度。
|