• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

中部:执具 | R语言数据分析(北京邮电大学)自整理笔记

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

第5章工欲善其事、必先利其器

代码,是延伸我们思想最好的工具。

第6章基础编程——用别人的包和函数讲述自己的故事

6.1编程环境

1.R语言的三段论

大前提:计算机语言程序=算法+数据结构

小前提:R语言不过是计算机语言的一种

结论:R语言约等于基础编程+数据对象

2.运行机制

RStudio=记事本+R Console

6.2Mini案例

学生文理分科小案例(还有问题)

R仅有的命令形式是返回结果的函数和表达式

赋值是一种常见的操作:对象的读取、转换、模型的建立等

赋值给新的对象,往往也意味着数据的流转:读取、转换、探索、建模、评估等操作。

6.3站在巨人的肩膀上

 

 

 

1.编程的法则:

R编程=用别人的包和函数讲述自己的故事

2.如何搜索包

①上百度

②逛论坛,找答案,[r]搜索

https://stackoverflow.com/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.githubusercontent.com/byaxb/RDataAnalytics/master/data/presidents.jpg"
 > download.file(jpg_url,"presidents.jpg",mode = "wb")
 试开URL’https://raw.githubusercontent.com/byaxb/RDataAnalytics/master/data/presidents.jpg\'
 Error in download.file(jpg_url, "presidents.jpg", mode = "wb") :
  无法打开URL\'https://raw.githubusercontent.com/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

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap