亚灿网志

R语言学习笔记

R语言认识

R语言特点

  1. 有效的数据处理和保存机制。
  2. 拥有一整套数组和矩阵的操作运算符。
  3. 一系列连贯而又完整的数据分析中间工具。
  4. 图形统计可以对数据直接进行分析和显示,可用于多种图形设备。
  5. 一种相当完善、简洁和高效的程序设计语言。
  6. R语言是彻底面向对象的统计编程语言。
  7. R语言和其它编程语言、数据库之间有很好的接口。
  8. R语言是自由软件,可以放心大胆地使用,但其功能却不比任何其它同类软件差。
  9. R语言具有丰富的网上资源。

R语言学习网站

  1. 官网:https://www.r-project.org
  2. RStudio:https://www.rstudio.com

在R官网下载一个R的exe程序,RStudio是一个R专用的IDE。

基本操作

R version 4.1.3 (2022-03-10) -- "One Push-Up"
Copyright (C) 2022 The R Foundation for Statistical Computing
Platform: x86_64-w64-mingw32/x64 (64-bit)

R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.

R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.

Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.

> getwd() ## 获取当前R工作目录
[1] "C:/Users/myxc/Documents"
> setwd(dir = "D:/R") ## 自定义R工作目录
> getwd() ## 重新查看R工作目录,会发现已经更改为上一步所设置的。
[1] "D:/R"
> list.files() ## 查看R工作目录下的所有文件和文件夹(不能查看嵌套文件夹里的文件)。
[1] "RData" "Study"
> dir() ## 这个命令与上一步相同
[1] "RData" "Study"
> 1 + 2 ## 在R中直接进行计算
[1] 3
> x <- 1 ## 在R中进行赋值
> y = 1 ## 这种赋值操作可以,但是不推荐在R中使用
> z <<- 1 ## 将全局变量“x”赋值为“1”(“<-”此种赋值方式操作得到的是局部变量)
> m <- max(5, 6, 7) # 将“5,6,7”中最大的值赋给m
> n = mean(8, 9, 10) # 将“8,9,10”的平均值赋给局部变量n
> v = sum(3, 4, 5) # 将“3,4,5”的和赋给局部变量v
> ls() # 查看所有变量
[1] "m" "n" "v" "x" "y" "z"
> ls.str() # 查看所有变量及其类型
m :  num 7
n :  num 8
v :  num 12
x :  num 1
y :  num 1
z :  num 1
> str(m) # 查看单个变量及其类型
 num 7
> rm(x) # 删除变量x
> x # 局部变量x已经被删除
Error: object 'x' not found
> ls.str()
m :  num 7
n :  num 8
v :  num 12
y :  num 1
z :  num 1
> rm(m, n) # 同时删除多个变量
> ls.str()
v :  num 12
y :  num 1
z :  num 1
> rm(list = ls()) # 删除所有变量
> ls.str()
> history() # 显示所有历史命令
> history(10) # 显示最后10条历史命令
> save.image() # 保存当前工作空间(会在之前设置的R工作目录中生成一个“.RData”文件)
> q() # 保存当前工作空间
Save workspace image to D:/R/.RData? [y/n]: 

R包操作

安装

中科大R镜像:https://mirrors.ustc.edu.cn/CRAN/index.html

官方:https://cloud.r-project.org/

[photos]

[/photos]

R version 4.1.3 (2022-03-10) -- "One Push-Up"
Copyright (C) 2022 The R Foundation for Statistical Computing
Platform: x86_64-w64-mingw32/x64 (64-bit)

R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.

R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.

Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.

[Workspace loaded from D:/R/.RData]

> install.packages("vcd") # 安装R包
WARNING: Rtools is required to build R packages but is not currently installed. Please download and install the appropriate version of Rtools before proceeding:

https://cran.rstudio.com/bin/windows/Rtools/
将程序包安装入‘C:/Users/myxc/Documents/R/win-library/4.1’
(因为‘lib’没有被指定)
trying URL 'https://cran.rstudio.com/bin/windows/contrib/4.1/vcd_1.4-9.zip'
Content type 'application/zip' length 1293641 bytes (1.2 MB)
downloaded 1.2 MB

package ‘vcd’ successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\myxc\AppData\Local\Temp\RtmpSWB6cz\downloaded_packages
> .libPaths() # 显示R默认安装的包的位置
[1] "C:/Users/myxc/Documents/R/win-library/4.1" "C:/Program Files/R/R-4.1.3/library"       
> library() # 显示当前R环境中所有包
> install.packages(c("AER", "ca")) # 同时安装多个包
WARNING: Rtools is required to build R packages but is not currently installed. Please download and install the appropriate version of Rtools before proceeding:

https://cran.rstudio.com/bin/windows/Rtools/
将程序包安装入‘C:/Users/myxc/Documents/R/win-library/4.1’
(因为‘lib’没有被指定)
trying URL 'https://cran.rstudio.com/bin/windows/contrib/4.1/AER_1.2-9.zip'
Content type 'application/zip' length 2498423 bytes (2.4 MB)
downloaded 2.4 MB

trying URL 'https://cran.rstudio.com/bin/windows/contrib/4.1/ca_0.71.1.zip'
Content type 'application/zip' length 243631 bytes (237 KB)
downloaded 237 KB

package ‘AER’ successfully unpacked and MD5 sums checked
package ‘ca’ successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\myxc\AppData\Local\Temp\RtmpSWB6cz\downloaded_packages
> update.packages() # 更新R包
Warning: package 'cluster' in library 'C:/Program Files/R/R-4.1.3/library' will not be updated
Warning: package 'MASS' in library 'C:/Program Files/R/R-4.1.3/library' will not be updated
Warning: package 'Matrix' in library 'C:/Program Files/R/R-4.1.3/library' will not be updated
Warning: package 'mgcv' in library 'C:/Program Files/R/R-4.1.3/library' will not be updated
Warning: package 'nlme' in library 'C:/Program Files/R/R-4.1.3/library' will not be updated
Warning: package 'survival' in library 'C:/Program Files/R/R-4.1.3/library' will not be updated
lme4 :
 Version 1.1-28 installed in C:/Users/myxc/Documents/R/win-library/4.1 
 Version 1.1-29 available at https://cran.rstudio.com

  有二进制版本的,但源代码版本是后来的:
     binary source needs_compilation
lme4 1.1-28 1.1-29              TRUE

  Binaries will be installed
trying URL 'https://cran.rstudio.com/bin/windows/contrib/4.1/lme4_1.1-28.zip'
Content type 'application/zip' length 5349899 bytes (5.1 MB)
downloaded 5.1 MB

package ‘lme4’ successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\myxc\AppData\Local\Temp\RtmpSWB6cz\downloaded_packages
> 

使用

R自带基础包:

> .libPaths() # 查看R包默认安装位置
[1] "C:/Users/myxc/Documents/R/win-library/4.1" "C:/Program Files/R/R-4.1.3/library"       
> library() # 查看本机环境中的所有R包
> library(vcd) # 环境中还未安装“vcd”包
Error in library(vcd) : 不存在叫‘vcd’这个名字的程辑包
> install.packages("vcd") # 安装“vcd”包
> install.packages("AER") # 安装“vcd”包
WARNING: Rtools is required to build R packages but is not currently installed. Please download and install the appropriate version of Rtools before proceeding:

https://cran.rstudio.com/bin/windows/Rtools/
将程序包安装入‘C:/Users/myxc/Documents/R/win-library/4.1’
(因为‘lib’没有被指定)
trying URL 'https://cran.rstudio.com/bin/windows/contrib/4.1/AER_1.2-9.zip'
Content type 'application/zip' length 2498423 bytes (2.4 MB)
downloaded 2.4 MB

package ‘AER’ successfully unpacked and MD5 sums checked
Error in install.packages : ERROR: failed to lock directory ‘C:\Users\myxc\Documents\R\win-library\4.1’ for modifying
Try removing ‘C:\Users\myxc\Documents\R\win-library\4.1/00LOCK’
> library(AER)
载入需要的程辑包:car
载入需要的程辑包:carData
载入需要的程辑包:lmtest
载入需要的程辑包:zoo

载入程辑包:‘zoo’

The following objects are masked from ‘package:base’:

    as.Date, as.Date.numeric

载入需要的程辑包:sandwich
载入需要的程辑包:survival
> require(AER)
> help("package:AER") # 显示”AER“包的帮助文档
No documentation for ‘package:AER’ in specified packages and libraries:
you could try ‘??package:AER’
> help(package="AER") # 显示”AER“包的帮助文档
> library(help="AER") # 显示“AER”包的数据集
> NMES1988
Error: object 'NMES1988' not found
> Affairs
Error: object 'Affairs' not found
> ls("package:AER") # 显示包中所有的函数
[1] "dispersiontest" "ivreg"          "ivreg.fit"      "tobit"         
> data(package="AER") # 显示包中所有数据集
> detach("package:AER") # 从内存中移除“AER”包(注意,并不是删除环境中的“AER”包)
> require(AER)
载入需要的程辑包:AER
> remove.packages("AER") # 删除环境中的“AER”包
从‘C:/Users/myxc/Documents/R/win-library/4.1’中删除程序包
(因为没有指定‘lib’)
> # 如何将本计算机环境中的所有R包移植到另一台计算机?(R无备份功能)

Tip: 如何将本计算机环境中的所有R包移植到另一台计算机?(R无备份功能)

# 导出原计算机环境中的所有R包,将所有R包的名字导出为一个文件
> backup_R_package = installed.packages()[,1]
> save(backup_R_package, file = "backup_R_package.Rdata")
# 在新的计算机里遍历循环安装R包
> for (i in backup_R_package) install.packages(i) # 批量安装

获取帮助

> help.start() # 显示帮助文档
If nothing happens, you should open
‘http://127.0.0.1:31250/doc/html/index.html’ yourself

> help(sum) # 打开sum函数的帮助文档
Warning messages:
1: In read.dcf(file.path(p, "DESCRIPTION"), c("Package", "Version")) :
  cannot open compressed file 'C:/Users/myxc/Documents/R/win-library/4.1/AER/DESCRIPTION', probable reason 'No such file or directory'
2: In find.package(if (is.null(package)) loadedNamespaces() else package,  :
  不存在叫‘AER’这个名字的程辑包
> ?sum # 与上一步操作一个意思
Warning messages:
1: In read.dcf(file.path(p, "DESCRIPTION"), c("Package", "Version")) :
  cannot open compressed file 'C:/Users/myxc/Documents/R/win-library/4.1/AER/DESCRIPTION', probable reason 'No such file or directory'
2: In find.package(if (is.null(package)) loadedNamespaces() else package,  :
  不存在叫‘AER’这个名字的程辑包

> args(sum) # 显示sum函数需要哪些参数
function (..., na.rm = FALSE) 
NULL

一个R搜索帮助的网站:https://rseek.org

> example("mean") # 获取mean函数的举例

mean> x <- c(0:10, 50)

mean> xm <- mean(x)

mean> c(xm, mean(x, trim = 0.10))
[1] 8.75 5.50
> demo(graphics)


    demo(graphics)
    ---- ~~~~~~~~

Type  <Return>     to start : 
...
> help(package="ggplot2") # 获取ggplot2包的帮助文档
> vignette() # 获取更加规划的官方文档
> help.search("heatmap") # 在本地搜索heatmap相关的内容
> ??heatmap # 与上一步相同
> apropos("sum") # 列出所有包含“sum”关键字的内容
 [1] ".colSums"                ".rowSums"                ".rs.callSummary"         ".rs.summarizeDir"       
> apropos("sum", mode = "function") # 列出所有包含“sum”关键字的内容,只搜索函数相关
 [1] ".colSums"                ".rowSums"                ".rs.callSummary"         ".rs.summarizeDir"         
> RSiteSearch("sum") # 联网搜索
A search query has been submitted to http://search.r-project.org
计算结果应很快就在瀏覽器里打开
> 

内置数据集

> help(package="datesets") # 打开R中数据集的帮助文档
> help(package="datasets") # 打开R中数据集的帮助文档
> data()
> data() # 显示所有数据集
> rivers # 数据集中的一个河流数据
  [1]  735  320  325  392  524  450 1459  135  465  600  330  336  280  315  870  906  202  329  290 1000  600  505 1450
 [24]  840 1243  890  350  407  286  280  525  720  390  250  327  230  265  850  210  630  260  230  360  730  600  306
 [47]  390  420  291  710  340  217  281  352  259  250  470  680  570  350  300  560  900  625  332 2348 1171 3710 2315
 [70] 2533  780  280  410  460  260  255  431  350  760  618  338  981 1306  500  696  605  250  411 1054  735  233  435
 [93]  490  310  460  383  375 1270  545  445 1885  380  300  380  377  425  276  210  800  420  350  360  538 1100 1205
[116]  314  237  610  360  540 1038  424  310  300  444  301  268  620  215  652  900  525  246  360  529  500  720  270
[139]  430  671 1770
> rivers <- 1 # 在定义变量的时候,尽量要避开这些变量名
> rivers
[1] 1
> data("rivers") # 如果变量名被覆盖,需要重新加载
> rivers
  [1]  735  320  325  392  524  450 1459  135  465  600  330  336  280  315  870  906  202  329  290 1000  600  505 1450
 [24]  840 1243  890  350  407  286  280  525  720  390  250  327  230  265  850  210  630  260  230  360  730  600  306
 [47]  390  420  291  710  340  217  281  352  259  250  470  680  570  350  300  560  900  625  332 2348 1171 3710 2315
 [70] 2533  780  280  410  460  260  255  431  350  760  618  338  981 1306  500  696  605  250  411 1054  735  233  435
 [93]  490  310  460  383  375 1270  545  445 1885  380  300  380  377  425  276  210  800  420  350  360  538 1100 1205
[116]  314  237  610  360  540 1038  424  310  300  444  301  268  620  215  652  900  525  246  360  529  500  720  270
[139]  430  671 1770

数据结构

数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。

数据类型

  1. 数值型,数值可以用于直接结算,加减乘除;
  2. 字符串型,可以进行连接,转换,提取等;
  3. 逻辑型, 真或者假;
  4. 日期型等。

普通数据结构:向量、标量、列表、数组、多维数组。

特殊数据结构:

  1. perl中的哈希
  2. python中的字典
  3. C语言中的指针等

对象:object,它是指可以赋值给变量的任何事物,包括常量、数据结构、函数,甚至图形。对象都拥有某种模式,描述了此对象是如何存储的,以及某个类。

向量

向量:vector,是R中最重要的一个概念,它是构成其他数据结构的基础。R中的向量概念与数学中向量是不同的,类似于数学上的集合的概念,由一个或多个元素所构成。

向量其实是用于存储数值型、字符型或逻辑型数据的一维数组。

用函数c来创建向量。c代表concatenate连接 ,也可以理解为收集collect,或者合并combine。

> x = c(1, 2, 3) # 在R中创建一个数值向量
> x
[1] 1 2 3
> x[1] # R中向量尽然是从1开始计数的?就离谱。
[1] 1
> y = c("one", "two", "three") # 创建一个字符串向量
> y[1]
[1] "one"
> z <- c(TRUE, T, F) # 创建一个布尔值向量
> z
[1]  TRUE  TRUE FALSE
> v <- True # 布尔值的这种写法在R中是不认可的
Error: object 'True' not found
> c(1:100) # 创建一个从1到100的数值向量
  [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  26  27  28
 [29]  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56
 [57]  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83  84
 [85]  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 100
> seq(from=1, to=100) # 与上一步作用相同
  [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  26  27  28
 [29]  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56
 [57]  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83  84
 [85]  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 100
> seq(from=1, to=100, by=2) # 创建一个从1到100,且间隔为2的数值向量
 [1]  1  3  5  7  9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55 57 59 61 63 65 67 69 71 73 75
[39] 77 79 81 83 85 87 89 91 93 95 97 99
> seq(from=1, to=100, length.out=10) # 创建一个从1到100,且长度为10的数值向量
 [1]   1  12  23  34  45  56  67  78  89 100
> rep(1, 5) # 创建一个将1重复5次的数值向量
[1] 1 1 1 1 1
> rep(x, 5) # 创建一个将向量x重复5次的数值向量
 [1] 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
> x
[1] 1 2 3
> rep(x, each=2, times=3) # 创建一个将向量x中的每个数值重复2次,且数值向量x整体重复3次的数值向量
 [1] 1 1 2 2 3 3 1 1 2 2 3 3 1 1 2 2 3 3
> a <- c(1, 2, "three") # 向量中的元素值类型必须为一致,否则会强制转化
> a
[1] "1"     "2"     "three"
> mode(a) # 向量a中的元素已经被强制转化为字符串类型
[1] "character"
> mode(a[1])
[1] "character"
> x <- c(1, 2, 3, 4, 5)
> y <- c(2, 4, 6, 8, 10)
> z <- x*2+y # R中向量类型的优点:更加方便做统计运算
> z
[1]  4  8 12 16 20
> rep(x, y) # 将数值向量x中的每个元素对应数值向量y中的数值进行重复
 [1] 1 1 2 2 2 2 3 3 3 3 3 3 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 5 5

向量的索引

  1. 正(负)整数索引;
  2. 逻辑向量索引;
  3. 名称索引。
> x <- c(1:100) # 创建一个数值型向量,里面元素从1到100
> 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  26  27  28
 [29]  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56
 [57]  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83  84
 [85]  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 100
> length(x) # 获取向量x的长度,即其内部有多少元素
[1] 100
> x[1] # x向量中第1个元素
[1] 1
> x[-1] # 显示x向量中除了第一个元素的所有元素
 [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  28  29  30
[30]  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59
[59]  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88
[88]  89  90  91  92  93  94  95  96  97  98  99 100
> x[c(2:10)] # 访问x向量中第2到第10个元素
[1]  2  3  4  5  6  7  8  9 10
> x[c(2, 6, 78, 99)] # 访问x向量中第2、6、78、99个元素
[1]  2  6 78 99
> x[c(-1, -10:-99)] # 访问x向量中除了第1、第10~第99个元素以外的所有元素
[1]   2   3   4   5   6   7   8   9 100
> x[c(1, -10:-99)] # 访问x向量中除了第1、第10~第99个元素以外的所有元素
Error in x[c(1, -10:-99)] : 
  only 0's may be mixed with negative subscripts
> x[c(1, -10:-99)] # 但是两种访问方式不能同时出现
Error in x[c(1, -10:-99)] : 
  only 0's may be mixed with negative subscripts
> y <- c(1:10) # 创建一个数值型向量,里面元素从1到10
> y
 [1]  1  2  3  4  5  6  7  8  9 10
> y[c(T, F, T, F, T, F, T, F, T, F)] # 输出y向量中的奇数值(因为序号为奇数对应的值都为TRUE)
[1] 1 3 5 7 9
> 
> y[c(F, T)] # 输出y向量中的偶数值
[1]  2  4  6  8 10
> y[c(F, F, T)] # 输出y向量中3的倍数
[1] 3 6 9
> y[c(F, F, T, F, F, T, F, F, T, F, F)] # 输出y向量中3的倍数(注意:此处y向量的长度为10,但是此处对应的布尔值有11个)
[1] 3 6 9
> y[c(F, F, T, F, F, T, F, F, T, T, T)] # 当要输出的序号超出向量的长度时
[1]  3  6  9 10 NA
> y[y>5 & y<7] # 输出y向量中大于5且小于7的值
[1] 6
> 3/3
[1] 1
> 3/2
[1] 1.5
> 3%2
Error: unexpected input in "3%2"
> y[y<2 | y>7] # 输出y向量中小于2或者大于7的值
[1]  1  8  9 10

%in%在字符串向量中的使用

> x <- c("one", "two", "three", "four", "five") # 创建一个字符串向量x
> "one" %in% x # 判断字符串“one”是否在向量x中,返回一个布尔值
[1] TRUE
> "One" %in% x # 区分大小写
[1] FALSE
> y <- c("one", "two", "three")
> y %in% x # 判断向量y中的元素是否在向量x中
[1] TRUE TRUE TRUE
> x %in% y # 判断向量x中的元素是否在向量y中
[1]  TRUE  TRUE  TRUE FALSE FALSE
> x[x %in% y] # 显示既存在于向量x中,又存在于向量y中的元素
[1] "one"   "two"   "three"

向量的名字

> x <- c(1, 2, 3, 4, 5)
> y <- c("one", "two", "three", "four", "five") # 创建一个字符串向量
> name(x) # 显示向量x的名字(其实就像是Excel中的表头)
Error in name(x) : could not find function "name"
> name(x) <- y # 将向量y作为向量x的名字
Error in name(x) <- y : could not find function "name<-"
> names(x) # 显示向量x的名字(其实就像是Excel中的表头)
NULL
> names(x) <- y # 将向量y作为向量x的名字
> x
  one   two three  four  five 
    1     2     3     4     5 
> x["one"] # 定义了表头之后,就可以以表头来访问向量中的元素
one 
  1 
> x[c("one", "two")]
one two 
  1   2 
> x[c(1, 2)]
one two 
  1   2 

向量的增删

> x <- c(1:5)
> x
[1] 1 2 3 4 5
> x[10] <- 10 # 将向量x的第10个元素赋值为10
> x # 中间未被赋值的将被默认填充为NA
 [1]  1  2  3  4  5 NA NA NA NA 10
> append(x, 66, after = 3) # 在向量x的第3个元素后面插入一个值为66的元素
 [1]  1  2  3 66  4  5 NA NA NA NA 10
> x
 [1]  1  2  3  4  5 NA NA NA NA 10
> rm(x) # 删除向量x
> x
Error: object 'x' not found
> x <- c(1:5) #创建一个数值向量
> x
[1] 1 2 3 4 5
> x <- x[-c(1:3)] # 剔除向量x中的前三个元素
> x
[1] 4 5

向量与向量的运算

> x <- seq(1, 100, by=10)
> x
 [1]  1 11 21 31 41 51 61 71 81 91
> y <- c(1:10)
> y
 [1]  1  2  3  4  5  6  7  8  9 10
> x+y
 [1]   2  13  24  35  46  57  68  79  90 101
> x-y
 [1]  0  9 18 27 36 45 54 63 72 81
> x*y
 [1]   1  22  63 124 205 306 427 568 729 910
> x/y
 [1] 1.000000 5.500000 7.000000 7.750000 8.200000 8.500000 8.714286 8.875000 9.000000 9.100000
> y**x # 开平方
 [1] 1.000000e+00 2.048000e+03 1.046035e+10 4.611686e+18 4.547474e+28 4.849688e+39 3.556153e+51 1.316404e+64
 [9] 1.966271e+77 1.000000e+91
> x%%y # 整除
 [1] 0 1 0 3 1 3 5 7 0 1
> x%%y # 取余
 [1] 0 1 0 3 1 3 5 7 0 1
> x%/%y # 整除
 [1] 1 5 7 7 8 8 8 8 9 9

两个进行运算的向量的长度必须相等,或者一个为另一个的整数倍:

> x <- c(1:10)
> y <- c(1, 2)
> z <- c(1:3)
> x+y
 [1]  2  4  4  6  6  8  8 10 10 12
> x
 [1]  1  2  3  4  5  6  7  8  9 10
> y+x
 [1]  2  4  4  6  6  8  8 10 10 12
> x+z
 [1]  2  4  6  5  7  9  8 10 12 11
Warning message:
In x + z : longer object length is not a multiple of shorter object length

常用运算函数

> x <- c(-5.5, -5.3, 3.2, 3,8)
> abs(x) # 绝对值
[1] 5.5 5.3 3.2 3.0 8.0
> sqrt(x) # 开平方
[1]      NaN      NaN 1.788854 1.732051 2.828427
Warning message:
In sqrt(x) : NaNs produced
> sqrt(-5.5) # 开平方
[1] NaN
Warning message:
In sqrt(-5.5) : NaNs produced
> sqrt(-5) # 开平方
[1] NaN
Warning message:
In sqrt(-5) : NaNs produced
> sqrt (-5) # 开平方
[1] NaN
Warning message:
In sqrt(-5) : NaNs produced
> sqrt(x[c(3:4)]) # 开根号
[1] 1.788854 1.732051
> log(x[c(3:4)]) # 对数
[1] 1.163151 1.098612
> log10(10) # 对数
[1] 1
> log(16, base = 2) # 对数
[1] 4
> ceiling(x)
[1] -5 -5  4  3  8
> x
[1] -5.5 -5.3  3.2  3.0  8.0
> ceiling(x) # 向上取整
[1] -5 -5  4  3  8
> floor(x) # 向下取整
[1] -6 -6  3  3  8
> trunc(x) # 保留整数部分
[1] -5 -5  3  3  8
> round(x, digits = 2) # 保留两位小数
[1] -5.5 -5.3  3.2  3.0  8.0
> round(x, digits = 3) # 保留两位小数
[1] -5.5 -5.3  3.2  3.0  8.0
> sin(x) # 三角函数
[1]  0.70554033  0.83226744 -0.05837414  0.14112001  0.98935825
> cos(x)
[1]  0.7086698  0.5543743 -0.9982948 -0.9899925 -0.1455000
> x <- c(1:100)
> sum(x) # 求和
[1] 5050
> max()
[1] -Inf
Warning message:
In max() : no non-missing arguments to max; returning -Inf
> max(x) # 求最大值
[1] 100
> min(x) # 求最小值
[1] 1
> range(x) # 求范围(即最大值和最小值)
[1]   1 100
> mean(x) # 中位数
[1] 50.5
> var(x) # 方差
[1] 841.6667
> sd(x) # 标准差
[1] 29.01149
> prod(x) # 求连乘
[1] 9.332622e+157
> median(x) # 平均值
[1] 50.5
> quantile(x) # 四分位数
    0%    25%    50%    75%   100% 
  1.00  25.75  50.50  75.25 100.00 
> quantile(x, c(0.2, 0.5, 0.8)) # 自定义分割
 20%  50%  80% 
20.8 50.5 80.2 

知道值反求索引

> x <- c(1:10)
> x
 [1]  1  2  3  4  5  6  7  8  9 10
> which.max(x) # 求向量x中最大值的索引
[1] 10
> which.min(x) # 求向量x中最小值的索引
[1] 1
> which(x == 5) # 求向量x中数值等于5
[1] 5
> which(x == 11) # 求向量x中数值等于11的元素的位置
integer(0)
> which(x > 5) # 求向量x中数值大于5的元素的位置
[1]  6  7  8  9 10

矩阵与数组

矩阵(Matrix)是一个按照长方阵列排列的复数或实数集合。向量是一维的,而矩阵是二维的,需要有行和列。

在R软件中,矩阵是有维数的向量,这里的矩阵元素可以是数值型,字符型或者逻辑型,但是每个元素必须都拥有相同的模式,这个和向量一致。

创建矩阵

> x <- matrix(1:100, nrow = 10, ncol = 10) # 创建一个10行10列的矩阵,元素为1到100(默认竖向开始)
> x
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
 [1,]    1   11   21   31   41   51   61   71   81    91
 [2,]    2   12   22   32   42   52   62   72   82    92
 [3,]    3   13   23   33   43   53   63   73   83    93
 [4,]    4   14   24   34   44   54   64   74   84    94
 [5,]    5   15   25   35   45   55   65   75   85    95
 [6,]    6   16   26   36   46   56   66   76   86    96
 [7,]    7   17   27   37   47   57   67   77   87    97
 [8,]    8   18   28   38   48   58   68   78   88    98
 [9,]    9   19   29   39   49   59   69   79   89    99
[10,]   10   20   30   40   50   60   70   80   90   100
> y <- matrix(1:20, 4, byrow = T) # # 创建一个4行的矩阵,元素为1到20(横向开始),byrow的参数默认为F
> y
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    2    3    4    5
[2,]    6    7    8    9   10
[3,]   11   12   13   14   15
[4,]   16   17   18   19   20

为矩阵的每一维添加名字

> rnames <- c("C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "C10")
> cnames <- c("R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9", "R10")
> dimnames(x) <- list(rnames, cnames) # 为矩阵x添加行、列名称
> x
    R1 R2 R3 R4 R5 R6 R7 R8 R9 R10
C1   1 11 21 31 41 51 61 71 81  91
C2   2 12 22 32 42 52 62 72 82  92
C3   3 13 23 33 43 53 63 73 83  93
C4   4 14 24 34 44 54 64 74 84  94
C5   5 15 25 35 45 55 65 75 85  95
C6   6 16 26 36 46 56 66 76 86  96
C7   7 17 27 37 47 57 67 77 87  97
C8   8 18 28 38 48 58 68 78 88  98
C9   9 19 29 39 49 59 69 79 89  99
C10 10 20 30 40 50 60 70 80 90 100

矩阵的维数

> x <- c(1:20) # 创建一个向量x
> dim(x) # 向量的维数是0
NULL
> dim(x) <- c(4, 5) # 将向量x的维数改为4行5列
> x
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    5    9   13   17
[2,]    2    6   10   14   18
[3,]    3    7   11   15   19
[4,]    4    8   12   16   20
> y <- (1:30) # 创建一个向量y
> dim(y) # 向量y的维数默认是0
NULL
> dim(y) <- c(3, 2, 5) # 将向量y的维数改为3行2列,高度为5(相当于一个长宽高分别为3、2、5的长方体)
> y
, , 1

     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6

, , 2

     [,1] [,2]
[1,]    7   10
[2,]    8   11
[3,]    9   12

, , 3

     [,1] [,2]
[1,]   13   16
[2,]   14   17
[3,]   15   18

, , 4

     [,1] [,2]
[1,]   19   22
[2,]   20   23
[3,]   21   24

, , 5

     [,1] [,2]
[1,]   25   28
[2,]   26   29
[3,]   27   30

array函数

> ?array # 打开array函数的用法
> arr_name_1 <- c("A1", "A2")
> arr_name_2 <- c("B1", "B2", "B3")
> arr_name_3 <- c("C1", "C2", "C3", "C4")
> array(1:24, c(2, 3, 4), dimnames = list(arr_name_1, arr_name_2, arr_name_3)) # 创建一个矩阵,元素为1到24,维数为2*3*4,并为每个维度添加名字
, , C1

   B1 B2 B3
A1  1  3  5
A2  2  4  6

, , C2

   B1 B2 B3
A1  7  9 11
A2  8 10 12

, , C3

   B1 B2 B3
A1 13 15 17
A2 14 16 18

, , C4

   B1 B2 B3
A1 19 21 23
A2 20 22 24

访问矩阵中的元素

访问单个元素

> x <- matrix(1:20, 4, 5) # 创建一个矩阵,元素为1到20,4行5列
> x
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    5    9   13   17
[2,]    2    6   10   14   18
[3,]    3    7   11   15   19
[4,]    4    8   12   16   20
> x[1, 2] # 矩阵x中位于1行2列的元素
[1] 5
> x[1] # 矩阵x中的第一个元素
[1] 1
> x[6] # 矩阵x中第6个元素
[1] 6

访问多个元素

> x[2, c(2:4)] # 矩阵x中第2行,第2到4个元素
[1]  6 10 14
> x[c(3:4), c(2:4)] # 矩阵x中位于3到4行,2到4列的元素
     [,1] [,2] [,3]
[1,]    7   11   15
[2,]    8   12   16
> x[2,] # 矩阵x中第2行的元素
[1]  2  6 10 14 18
> x[,3] # 矩阵x中第3列的元素
[1]  9 10 11 12
> x[-1, 3] # 矩阵x中第三列出去第一个元素的剩下的所有元素
[1] 10 11 12

使用维名称访问元素

> x # 矩阵x
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    5    9   13   17
[2,]    2    6   10   14   18
[3,]    3    7   11   15   19
[4,]    4    8   12   16   20
> dimnames(x) <- list(c("B1", "B2", "B3", "B4"), c("A1", "A2", "A3", "A4", "A5")) # 为矩阵的行和列添加名字
> x
   A1 A2 A3 A4 A5
B1  1  5  9 13 17
B2  2  6 10 14 18
B3  3  7 11 15 19
B4  4  8 12 16 20
> x["B1", "A4"] # 访问矩阵x中位于B1行A4列的元素
[1] 13
> x["B1", c(2:5)] # 访问矩阵中位于B1行,第2至第5个元素
A2 A3 A4 A5 
 5  9 13 17 
> x["B1",] # 访问矩阵x中B1行的所有元素
A1 A2 A3 A4 A5 
 1  5  9 13 17 

矩阵的运算

> x+1 # 矩阵中所有元素都+1
   A1 A2 A3 A4 A5
B1  2  6 10 14 18
B2  3  7 11 15 19
B3  4  8 12 16 20
B4  5  9 13 17 21
> x+x # 矩阵对应的元素相加
   A1 A2 A3 A4 A5
B1  2 10 18 26 34
B2  4 12 20 28 36
B3  6 14 22 30 38
B4  8 16 24 32 40
> x*x # 矩阵中所有对应的元素相乘
   A1 A2  A3  A4  A5
B1  1 25  81 169 289
B2  4 36 100 196 324
B3  9 49 121 225 361
B4 16 64 144 256 400

矩阵常用的一些内置函数

> sum(x) # 矩阵中所有元素相加
[1] 210
> max(x) # 矩阵x中的最大值
[1] 20
> colSums(x) # 对矩阵中每一列求和
A1 A2 A3 A4 A5 
10 26 42 58 74 
> rowSums(x) # 对矩阵中每一行求和
B1 B2 B3 B4 
45 50 55 60 
> colMeans(x) # 对矩阵中每一列求平均值
  A1   A2   A3   A4   A5 
 2.5  6.5 10.5 14.5 18.5 
> y <- matrix(1:4, 2, 2)
> y
     [,1] [,2]
[1,]    1    3
[2,]    2    4
> z <- matrix(2:5, 2, 2)
> z
     [,1] [,2]
[1,]    2    4
[2,]    3    5
> y*z # 矩阵中对应元素相乘(外积)
     [,1] [,2]
[1,]    2   12
[2,]    6   20
> y%*%z # 求矩阵(内积)
     [,1] [,2]
[1,]   11   19
[2,]   16   28
> diag(x) # 求矩阵对角线元素
[1]  1  6 11 16
> t(x) # 矩阵求转置
   B1 B2 B3 B4
A1  1  2  3  4
A2  5  6  7  8
A3  9 10 11 12
A4 13 14 15 16
A5 17 18 19 20

修改矩阵的某一列

> data.frame(women$height*2.54, women$weight) # 这样修改有个问题,会导致列名称变得很长
   women.height...2.54 women.weight
1               147.32          115
...
> data.frame(height=women$height*2.54, weight=women$weight) # 修改的时候直接重新指定列名称
   height weight
1  147.32    115
...
> ?transform # 上面的修改方式本质上是“重新制造”了一个矩阵,并不是在原矩阵上进行修改,性能不高。
> transform(women, height=height*2.54) # 这才是高效的方式
   height weight
1  147.32    115
...
> transform(women, cm=height*2.54) # 你甚至可以新加一列
   height weight     cm
1      58    115 147.32
...

t()——转置

> head(mtcars)
                   mpg cyl disp  hp drat    wt  qsec vs am gear
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4
...
> head(t(mtcars))
     Mazda RX4 Mazda RX4 Wag Datsun 710 Hornet 4 Drive
mpg      21.00        21.000      22.80         21.400
cyl       6.00         6.000       4.00          6.000
disp    160.00       160.000     108.00        258.000
...

行求和与列求和

> WorldPhones  # 一个矩阵
     N.Amer Europe Asia S.Amer Oceania Africa Mid.Amer
1951  45939  21574 2876   1815    1646     89      555
1956  60423  29990 4708   2568    2366   1411      733
1957  64721  32510 5230   2695    2526   1546      773
1958  68484  35218 6662   2845    2691   1663      836
1959  71799  37598 6856   3000    2868   1769      911
1960  76036  40341 8220   3145    3054   1905     1008
1961  79831  43173 9053   3338    3224   2005     1076
> rowSums(WorldPhones)  # 行求和
  1951   1956   1957   1958   1959   1960   1961 
 74494 102199 110001 118399 124801 133709 141700 
> class(WorldPhones)  # 为什么它既是矩阵又是数据集???
[1] "matrix" "array" 
> colSums(WorldPhones)  # 列求和
  N.Amer   Europe     Asia   S.Amer  Oceania   Africa Mid.Amer 
  467233   240404    43605    19406    18375    10388     5892 
> transform(WorldPhones, sum=rowSums(WorldPhones)) # 行求和,并把求和结果添加到最后一列
     N.Amer Europe Asia S.Amer Oceania Africa Mid.Amer    sum
1951  45939  21574 2876   1815    1646     89      555  74494
1956  60423  29990 4708   2568    2366   1411      733 102199
1957  64721  32510 5230   2695    2526   1546      773 110001
1958  68484  35218 6662   2845    2691   1663      836 118399
1959  71799  37598 6856   3000    2868   1769      911 124801
1960  76036  40341 8220   3145    3054   1905     1008 133709
1961  79831  43173 9053   3338    3224   2005     1076 141700
> cbind(WorldPhones, sum=rowSums(WorldPhones))  # 另一种方式
     N.Amer Europe Asia S.Amer Oceania Africa Mid.Amer    sum
1951  45939  21574 2876   1815    1646     89      555  74494
1956  60423  29990 4708   2568    2366   1411      733 102199
1957  64721  32510 5230   2695    2526   1546      773 110001
1958  68484  35218 6662   2845    2691   1663      836 118399
1959  71799  37598 6856   3000    2868   1769      911 124801
1960  76036  40341 8220   3145    3054   1905     1008 133709
1961  79831  43173 9053   3338    3224   2005     1076 141700
> rbind(WorldPhones, sum=colSums(WorldPhones)) # 列求和,将求和结果作为新的一行赋值到最后一行
     N.Amer Europe  Asia S.Amer Oceania Africa Mid.Amer
1951  45939  21574  2876   1815    1646     89      555
1956  60423  29990  4708   2568    2366   1411      733
1957  64721  32510  5230   2695    2526   1546      773
1958  68484  35218  6662   2845    2691   1663      836
1959  71799  37598  6856   3000    2868   1769      911
1960  76036  40341  8220   3145    3054   1905     1008
1961  79831  43173  9053   3338    3224   2005     1076
sum  467233 240404 43605  19406   18375  10388     5892

apply()——自定义操作函数(矩阵&数据集)

> ?apply(array, margin, ...)  # 可以进行自定义function
> apply(WorldPhones, MARGIN = 1, FUN = sum())
Error in match.fun(FUN) : 'sum()'不是函数,也不是字符,也不是符號
> apply(WorldPhones, MARGIN = 1, FUN = sum) # MARGIN = 1 行操作
  1951   1956   1957   1958   1959   1960   1961 
 74494 102199 110001 118399 124801 133709 141700 
> apply(WorldPhones, MARGIN = 2, FUN = sum) # MARGIN = 2 列操作
  N.Amer   Europe     Asia   S.Amer  Oceania   Africa Mid.Amer 
  467233   240404    43605    19406    18375    10388     5892 
> apply(WorldPhones, MARGIN = 1, FUN = mean)
    1951     1956     1957     1958     1959     1960     1961 
10642.00 14599.86 15714.43 16914.14 17828.71 19101.29 20242.86 
> apply(WorldPhones, MARGIN = 1, FUN = max)
 1951  1956  1957  1958  1959  1960  1961 
45939 60423 64721 68484 71799 76036 79831 

矩阵与向量的排序问题

rev()——使向量、矩阵反序

> ?rev
> letters
 [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o"
[16] "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"
> rev(letters) # 向量的反序
 [1] "z" "y" "x" "w" "v" "u" "t" "s" "r" "q" "p" "o" "n" "m" "l"
[16] "k" "j" "i" "h" "g" "f" "e" "d" "c" "b" "a"
> women
   height weight
1      58    115
2      59    117
3      60    120
...
> women[rev(row.names(women)),] # 矩阵的反序
   height weight
15     72    164
14     71    159
13     70    154
...
注意,使用rev()函数反序的话,参数只能为矩阵的行名称,如果想使用某一列作为反序的参考,需要使用sort()函数,后面介绍。

sort()——向量与矩阵的排序

> rivers # 原数据
  [1]  735  320  325  392  524  450 1459  135  465  600  330  336 ...
> sort(rivers) # 默认正序
  [1]  135  202  210  210  215  217  230  230  233  237  246  250 ...
> sort(rivers, decreasing = T) # 倒序
  [1] 3710 2533 2348 2315 1885 1770 1459 1450 1306 1270 1243 1205 ...
> rev(sort(rivers)) # 与上一步作用一致,其余例子可以反推
  [1] 3710 2533 2348 2315 1885 1770 1459 1450 1306 1270 1243 1205 ...
> sort(state.name, decreasing = T) # 字符串型向量也是可以滴~
 [1] "Wyoming"        "Wisconsin"      "West Virginia" ...    
> sort(women$height) # ?
 [1] 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
?:sort()函数可以对矩阵的某一列进行排序(正序或者逆序),但是却不能对矩阵排序(利用排序的某一列不能去反推整个矩阵的排序)。举个例子:women数据为15个女人的身高、体重数据,使用sort()函数只能对这个矩阵数据的某一列数据(相当于一个向量,例如women$height,相当于单独把这一列拿出来,作为一个向量排序,已经失去了与原来矩阵的关联性)进行排序,并不能将15个女人按照身高的顺序进行排序。使用order()函数可以解决这个问题。

sort()函数对矩阵排序的话只有一种情况,就是排序参数是矩阵的行名称,这个时候sort函数是可以的。这是为什么呢?因为矩阵元素的访问方式可以通过每一行的行名称来访问这一行,但是不能通过这一行中的某一个元素来访问这一行。举个栗子:

> mtcars # 原数据
                     mpg cyl  disp  hp drat    wt  qsec vs am gear
Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4
Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4
...
> mtcars[sort(row.names(mtcars)),] # 按照行排序后的数据
                     mpg cyl  disp  hp drat    wt  qsec vs am gear
AMC Javelin         15.2   8 304.0 150 3.15 3.435 17.30  0  0    3
Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3
....
> mtcars[rev(sort(row.names(mtcars))),] # 设置可以结合rev()函数来个逆序
                     mpg cyl  disp  hp drat    wt  qsec vs am gear
Volvo 142E          21.4   4 121.0 109 4.11 2.780 18.60  1  1    4
Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3
...

order()——矩阵自定义排序

为了解决sort()函数的不足,便有了它。

举个例子:

> ?order
> rivers # 原向量
  [1]  735  320  325  392  524  450 1459  135  465  600  330  336 ...
> sort(rivers) # 排序后的向量(正序)
  [1]  135  202  210  210  215  217  230  230  233  237  246  250 ...
> order(rivers) # order()函数返回的是排序(正序)后对应的位置(下标)
  [1]   8  17  39 108 129  52  36  42  91 117 133  34  56  87  76 ...
> rivers[8] # 举个栗子:order()返回的第一个值是8,就说明rivers向量排序(正序)后,在第1个的元素是原来排在第8个位置的元素
[1] 135

找个矩阵练习下:

> mtcars # 一个矩阵数据
                     mpg cyl  disp  hp drat    wt  qsec vs am gear
Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4
...
> order(mtcars$mpg) # 按照矩阵中的mpg列进行排序,排在第一个的是15,就说明原来矩阵第15行对应的mpg值是这一列中最小的。
 [1] 15 16 24  7 17 31 14 23 22 29 12 13 11  6  5 10 25 30  1  2  4 ...
> mtcars[order(mtcars$mpg),] # 应为order()函数返回的是排序后原来每一行的下标(原来每一行的行号),这个时候就可以利用order()的返回值来对矩阵进行排序
                     mpg cyl  disp  hp drat    wt  qsec vs am gear
Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3
Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3
Camaro Z28          13.3   8 350.0 245 3.73 3.840 15.41  0  0    3
Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3
...
> mtcars[order(mtcars$mpg, decreasing = T),] # 如何逆序?添加参数
                     mpg cyl  disp  hp drat    wt  qsec vs am gear
Toyota Corolla      33.9   4  71.1  65 4.22 1.835 19.90  1  1    4
Fiat 128            32.4   4  78.7  66 4.08 2.200 19.47  1  1    4
Honda Civic         30.4   4  75.7  52 4.93 1.615 18.52  1  1    4
Lotus Europa        30.4   4  95.1 113 3.77 1.513 16.90  1  1    5
...
> mtcars[order(-mtcars$mpg),] # 一个逆序的骚操作,把原来的mpg列值全部变为负数再进行排序的话,原来的最大值就变成了最小值
                     mpg cyl  disp  hp drat    wt  qsec vs am gear
Toyota Corolla      33.9   4  71.1  65 4.22 1.835 19.90  1  1    4
Fiat 128            32.4   4  78.7  66 4.08 2.200 19.47  1  1    4
Honda Civic         30.4   4  75.7  52 4.93 1.615 18.52  1  1    4
Lotus Europa        30.4   4  95.1 113 3.77 1.513 16.90  1  1    5
...
> mtcars[rev(order(mtcars$mpg)),] # 使用rev()函数也可以逆序,原理:order()函数取出排序后的下标后,对下标使用rev()逆序。
                     mpg cyl  disp  hp drat    wt  qsec vs am gear
Toyota Corolla      33.9   4  71.1  65 4.22 1.835 19.90  1  1    4
Fiat 128            32.4   4  78.7  66 4.08 2.200 19.47  1  1    4
...

小问题:如何根据两列来排序?

> mtcars[order(mtcars$mpg),] 
                     mpg cyl  disp  hp drat    wt  qsec vs am gear
Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3
Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3
Camaro Z28          13.3   8 350.0 245 3.73 3.840 15.41  0  0    3
Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3
> mtcars[order(mtcars$mpg, mtcars$cyl),] # 当两行的mpg数据一样时,再根据cyl数据来排序
                     mpg cyl  disp  hp drat    wt  qsec vs am gear
Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3
Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3
Camaro Z28          13.3   8 350.0 245 3.73 3.840 15.41  0  0    3
...

列表

列表顾名思义就是用来存储很多内容的一个集合,在其他编程语言中列表一般和数组是等同的,但是在R语言中,列表却是R中最复杂的一种数据结构,也是非常重要的一种数据结构。

列表就是一些对象的有序集合。列表中可以存储若干向量、矩阵、数据框,甚至其他列表的组合。

列表特点:

  1. 在模式上和向量类似,都是一维数据集合。
  2. 向量只能存储一种数据类型,列表中的对象可以是R中的任何数据结构,甚至列表本身。

创建一个列表

> a <- (1:5)
> b <- matrix(1:20, 4)
> c <- 5
> d <- "This is a string."
> mlist <- list(a, b, c, d) # 定义一个列表
> mlist # 查看该列表
[[1]]
[1] 1 2 3 4 5

[[2]]
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    5    9   13   17
[2,]    2    6   10   14   18
[3,]    3    7   11   15   19
[4,]    4    8   12   16   20

[[3]]
[1] 5

[[4]]
[1] "This is a string."

访问列表中的元素

> mlist[1] # 访问列表中的第一个元素
[[1]]
[1] 1 2 3 4 5
> mlist[c(3, 4)] # 访问列表中第3和第4个元素
[[1]]
[1] 5

[[2]]
[1] "This is a string."

> mlist[[1]] # 访问列表中的第一个元素,注意:此种访问方式和上面的是不同的
[1] 1 2 3 4 5
> class(mlist[1]) # 通过“[]”方式访问的时候,访问的元素还是列表的格式
[1] "list"
> class(mlist[[1]]) # 通过“[[]]”方式访问的时候,访问的元素是该元素本身的格式
[1] "integer"

创建列表时指定元素的名称

> nlist <- list(first=a, second=b, third=c, forth=d) # 可以为列表中每个元素添加名字。就离谱,为啥有的可以不加引号,有的就需要加引号,R中变量的命名太离谱了!!!
> nlist
$first
[1] 1 2 3 4 5

$second
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    5    9   13   17
[2,]    2    6   10   14   18
[3,]    3    7   11   15   19
[4,]    4    8   12   16   20

$third
[1] 5

$forth
[1] "This is a string."

通过列表中元素的名字来访问该元素

> nlist$first # 通过列表内元素的名字访问各个元素
[1] 1 2 3 4 5
> nlist$forth
[1] "This is a string."
> nlist$second
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    5    9   13   17
[2,]    2    6   10   14   18
[3,]    3    7   11   15   19
[4,]    4    8   12   16   20
> nlist$second[1] # 注意:当通过列表内元素的名字来访问元素的时候,不需要使用“[[]]”的方式来进行访问
[1] 1
> nlist$second[1,]
[1]  1  5  9 13 17

> nlist[2] # 返回一个列表,该列表里只有一个元素,就是一个矩阵
$second
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    5    9   13   17
[2,]    2    6   10   14   18
[3,]    3    7   11   15   19
[4,]    4    8   12   16   20

> nlist[2][1] # 返回一个矩阵
$second
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    5    9   13   17
[2,]    2    6   10   14   18
[3,]    3    7   11   15   19
[4,]    4    8   12   16   20

> nlist[[2]][1] # 返回列表中第2个元素(一个矩阵)之中的第一个元素
[1] 1

> nlist[[2]][1, c(3:5)] # 返回列表中第2个元素(一个矩阵)之中的第一行中第3~5个元素
[1]  9 13 17
> class(b)
[1] "matrix" "array" 

访问列表中元素时的一个注意点

> class(nlist$second) # 通过列表中元素的名字直接访问元素($)时,可以直接访问到该元素,等同于使用“[[]]”方式访问
[1] "matrix" "array" 
> class(nlist[2]) # 通过“[]”访问列表中的元素,访问到的时“披着列表的皮的元素”
[1] "list"
> class(nlist[[2]]) # 想要直接访问到该元素需要使用“[[]]”方式访问
[1] "matrix" "array" 
> nlist[2][1][1] # 通过“套娃”的方式来访问是不行的
$second
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    5    9   13   17
[2,]    2    6   10   14   18
[3,]    3    7   11   15   19
[4,]    4    8   12   16   20

删除列表中的元素

> nlist[c(-1, -2)] # 删除列表中第1、第2个元素
$third
[1] 5

$forth
[1] "This is a string."

> nlist[4] <- NULL # 删除列表中第4个元素
> nlist$third <- NULL # 删除列表中名称为“third”的元素
> nlist
$first
[1] 1 2 3 4 5

$second
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    5    9   13   17
[2,]    2    6   10   14   18
[3,]    3    7   11   15   19
[4,]    4    8   12   16   20

lapply()与sapply()

> apply(WorldPhones, MARGIN = 1, FUN = sum)  # apply()函数可以应用于矩阵或者数据集数据
  1951   1956   1957   1958   1959   1960   1961 
 74494 102199 110001 118399 124801 133709 141700 
> state.center  # 但是对于列表型数据的话,apply()函数就不行了
$x
 [1]  -86.7509 -127.2500 -111.6250  -92.2992 -119.7730 -105.5130
 [7]  -72.3573  -74.9841  -81.6850  -83.3736 -126.2500 -113.9300
[13]  -89.3776  -86.0808  -93.3714  -98.1156  -84.7674  -92.2724
[19]  -68.9801  -76.6459  -71.5800  -84.6870  -94.6043  -89.8065
[25]  -92.5137 -109.3200  -99.5898 -116.8510  -71.3924  -74.2336
[31] -105.9420  -75.1449  -78.4686 -100.0990  -82.5963  -97.1239
[37] -120.0680  -77.4500  -71.1244  -80.5056  -99.7238  -86.4560
[43]  -98.7857 -111.3300  -72.5450  -78.2005 -119.7460  -80.6665
[49]  -89.9941 -107.2560

$y
 [1] 32.5901 49.2500 34.2192 34.7336 36.5341 38.6777 41.5928
 [8] 38.6777 27.8744 32.3329 31.7500 43.5648 40.0495 40.0495
[15] 41.9358 38.4204 37.3915 30.6181 45.6226 39.2778 42.3645
[22] 43.1361 46.3943 32.6758 38.3347 46.8230 41.3356 39.1063
[29] 43.3934 39.9637 34.4764 43.1361 35.4195 47.2517 40.2210
[36] 35.5053 43.9078 40.9069 41.5928 33.6190 44.3365 35.6767
[43] 31.3897 39.1063 44.2508 37.5630 47.4231 38.4204 44.5937
[50] 43.0504

> lapply(state.center, FUN = length) # lapply()函数返回一个list对象
$x
[1] 50

$y
[1] 50

> sapply(state.center, FUN = length) # sapply()函数返回一个向量对象,其两者的作用本质是一样的,都是对list对象应用函数操作
 x  y 
50 50 
> class(lapply(state.center, FUN = length)) # 返回列表对象
[1] "list"
> class(sapply(state.center, FUN = length)) # 返回向量对象
[1] "integer"

数据框

数据框是一种表格式的数据结构。数据框旨在模拟数据集,与其他统计软件例如SAS或者SPSS中的数据集的概念一致。

数据集通常是由数据构成的一个矩形数组,行表示观测,列表示变量。不同的行业对于数据集的行和列叫法不同。

数据框实际上是一个列表。列表中的元素是向量,这些向量构成数据框的列,每一列必须具有相同的长度,所以数据框是矩形结构,而且数据框的列必须命名。

数据框特点:

  1. 数据框形状上很像矩阵;
  2. 数据框是比较规则的列表;
  3. 矩阵必须为同一数据类型;
  4. 数据框每一列必须同一类型,每一行可以不同。
> state <- data.frame(state.name, state.region, state.abb, state.area, state.center, state.division, state.x77) # 创建一个数据框
> state[1] # 访问数据框的第一列
                   state.name
Alabama               Alabama
Alaska                 Alaska
Arizona               Arizona
...
> state["Area"] # 访问数据框的“Area”列
                 Area
Alabama         50708
Alaska         566432
Arizona        113417
Arkansas        51945
...
> state[,"state.abb"] # 访问数据框的“state.abb”列
 [1] "AL" "AK" "AZ" "AR" "CA" "CO" "CT" "DE" "FL" "GA" "HI" "ID" "IL" "IN" "IA" "KS" "KY" "LA" "ME" "MD" "MA" "MI" "MN"
> state$Area # 可以像列表一样用“$”访问
 [1]  50708 566432 113417  51945 156361 103766   4862   1982  54090  58073   6425  82677  55748  36097  55941  81787
[17]  39650  44930  30920   9891   7826  56817  79289  47296  68995 145587  76483 109889   9027   7521 121412  47831
[33]  48798  69273  40975  68782  96184  44966   1049  30225  75955  41328 262134  82096   9267  39780  66570  24070
[49]  54464  97203
> women
   height weight
1      58    115
2      59    117
3      60    120
4      61    123
5      62    126
6      63    129
7      64    132
8      65    135
9      66    139
10     67    142
11     68    146
12     69    150
13     70    154
14     71    159
15     72    164
> plot(women$height, women$weight)
> ?attach
> ?mtcars
> mtcars
                     mpg cyl  disp  hp drat    wt  qsec vs am gear carb
Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
...
> mtcars$mpg
 [1] 21.0 21.0 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 17.8 16.4 17.3 15.2 10.4 10.4 14.7 32.4 30.4 33.9 21.5 15.5 15.2
[24] 13.3 19.2 27.3 26.0 30.4 15.8 19.7 15.0 21.4
> attach(mtcars)
> mpg
 [1] 21.0 21.0 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 17.8 16.4 17.3 15.2 10.4 10.4 14.7 32.4 30.4 33.9 21.5 15.5 15.2
[24] 13.3 19.2 27.3 26.0 30.4 15.8 19.7 15.0 21.4
> detach(mtcars)
> mpg
Error: object 'mpg' not found
R中矩阵与数据框的区别:两者都表示矩形数据类型,这意味着它们用于存储具有行和列的表格数据。这两者的主要区别是,矩阵只能包含一种数据类型,而数据框可以包含多种数据类型。

merge()——数据框的合并

合并一个数据框(或者矩阵)与一个向量的方法:

> x <- data.frame(k1 = c(NA,NA,3,4,5), k2 = c(1,NA,NA,4,5),  # 两个矩阵对象
+                 data = 1:5)
> y <- data.frame(k1 = c(NA,2,NA,4,5), k2 = c(NA,NA,3,4,5),
+                 data = 1:5)
> x  # x向量一共也有5列
  k1 k2 data
1 NA  1    1
2 NA NA    2
3  3 NA    3
4  4  4    4
5  5  5    5
> y  # y向量一共也有5列
  k1 k2 data
1 NA NA    1
2  2 NA    2
3 NA  3    3
4  4  4    4
5  5  5    5
> transform(x, demo = y[,'k1'])  # 合并一个矩阵与一个向量
  k1 k2 data demo
1 NA  1    1   NA
2 NA NA    2    2
3  3 NA    3   NA
4  4  4    4    4
5  5  5    5    5

开始进入正题:

## 在分析之前,首先一点要知道:`merge()`函数取得是交集。首先,x与y有两列完全相同,那么着这两列肯定是交集了,那么必须有的,也就是对应下面的1、2两行;接下来因为是以k1列为参考,
> x[,'k1'] ## 可以看到,除了完全相同的4、5两行,还有x中的两个NA与y中的两个NA对应。2×2也就有了4种自由组合方式。
[1] NA NA  3  4  5
> y[,'k1']
[1] NA  2 NA  4  5
> merge(x, y, by = "k1")  ## 合并数据框x、y,以k1列为主参考
  k1 k2.x data.x k2.y data.y
1  4    4      4    4      4
2  5    5      5    5      5
3 NA    1      1   NA      1
4 NA    1      1    3      3
5 NA   NA      2   NA      1
6 NA   NA      2    3      3
## 换成k2列分析下:1、首先看下两个数据框的k2列对应的交集,交集应该为NA NA 4 5;
> x[,'k2']
[1]  1 NA NA  4  5
> y[,'k2']
[1] NA NA  3  4  5
## 那么对应的,4 5 对应的两行完全相同,那么自然是需要的,剩下的各自都有两个NA,又是2×2=4种排列组合。
> merge(x, y, by = "k2")
  k2 k1.x data.x k1.y data.y
1  4    4      4    4      4
2  5    5      5    5      5
3 NA   NA      2   NA      1
4 NA   NA      2    2      2
5 NA    3      3   NA      1
6 NA    3      3    2      2
## incomparables参数用来过滤“关键字”
> merge(x, y, by = "k2", incomparables = NA)
  k2 k1.x data.x k1.y data.y
1  4    4      4    4      4
2  5    5      5    5      5
> merge(x, y, by = "k2", incomparables = c(NA, 4))
  k2 k1.x data.x k1.y data.y
1  5    5      5    5      5
## 当同时以k1和k2为主参考时,那么必须只有k1与k2都完全一样才能被提取出来
> merge(x, y, by = c("k1", "k2"))
  k1 k2 data.x data.y
1  4  4      4      4
2  5  5      5      5
3 NA NA      2      1

因子

R中的变量分类

  1. 名义型变量(人名之类的,单一性,不连续性)
  2. 有序型变量(数字)
  3. 连续型变量(例如:women, men; bad, good, better, best,介于以上两者之间的)

因子,在R中名义型变量和有序性变量称为因子,factor。这些分类变量的可能值称为一个水平level,例如good,better,best,都称为一个level。由这些水平值构成的向量就称为因子。

因子的应用

  1. 计算频数
  2. 独立性检验
  3. 相关性检验
  4. 方差分析
  5. 主成分分析
  6. 因子分析
  7. ...

连续性变量举例

> mtcars # mtcars数据框
                     mpg cyl  disp  hp drat    wt  qsec vs am gear carb
Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
...
> mtcars['cyl'] # mtcars数据框中的cyl列(发动机缸数)就是连续性变量
                    cyl
Mazda RX4             6
Mazda RX4 Wag         6
Datsun 710            4
Hornet 4 Drive        6
...
> mtcars$cyl # 因为这一列的数据中只有4、6、8
 [1] 6 6 4 6 8 6 8 4 4 6 6 8 8 8 8 8 8 4 4 4 4 8 8 8 8 4 4 4 8 6 8 4
> table(mtcars$cyl) # 对这一列进行数据透析

 4  6  8

创建因子

> week <- factor(c("Mon", "Fri", "Thu", "Wed", "Mon", "Fri")) # 创建一个因子
> week # 查看该因子
[1] Mon Fri Thu Wed Mon Fri
Levels: Fri Mon Thu Wed
> week <- factor(c("Mon", "Fri", "Thu", "Wed", "Mon", "Fri"), levels = c("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"))  # 创建因子时指定levels,levels中的值不能重复,重复的话会报错
> week # 查看该因子
[1] Mon Fri Thu Wed Mon Fri
Levels: Mon Tue Wed Thu Fri Sat Sun
> week <- factor(c("Mon", "Fri", "Thu", "Wed", "Mon", "Fri"), levels = c("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"), ordered = T) # 创建因子,并对levels进行一个排序
> week
[1] Mon Fri Thu Wed Mon Fri
Levels: Mon < Tue < Wed < Thu < Fri < Sat < Sun

因子绘图举例

> demo_cyl <- factor(mtcars$cyl)
> plot(demo_cyl) # 绘制图2,观察把“mtcars$cyl”经过因子变换前后绘制图有什么区别
> plot(mtcars$cyl) # 绘制图1
> mtcars$cyl
 [1] 6 6 4 6 8 6 8 4 4 6 6 8 8 8 8 8 8 4 4 4 4 8 8 8 8 4 4 4 8 6 8 4
> demo_cyl
 [1] 6 6 4 6 8 6 8 4 4 6 6 8 8 8 8 8 8 4 4 4 4 8 8 8 8 4 4 4 8 6 8 4
Levels: 4 6 8
> x <- 1:100
> cut(x, c(seq(0, 100, 10)))
  [1] (0,10]   (0,10]   (0,10]   (0,10]   (0,10]   (0,10]   (0,10]  
  [8] (0,10]   (0,10]   (0,10]   (10,20]  (10,20]  (10,20]  (10,20] 
 [15] (10,20]  (10,20]  (10,20]  (10,20]  (10,20]  (10,20]  (20,30] 
 [22] (20,30]  (20,30]  (20,30]  (20,30]  (20,30]  (20,30]  (20,30] 
 [29] (20,30]  (20,30]  (30,40]  (30,40]  (30,40]  (30,40]  (30,40] 
 [36] (30,40]  (30,40]  (30,40]  (30,40]  (30,40]  (40,50]  (40,50] 
 [43] (40,50]  (40,50]  (40,50]  (40,50]  (40,50]  (40,50]  (40,50] 
 [50] (40,50]  (50,60]  (50,60]  (50,60]  (50,60]  (50,60]  (50,60] 
 [57] (50,60]  (50,60]  (50,60]  (50,60]  (60,70]  (60,70]  (60,70] 
 [64] (60,70]  (60,70]  (60,70]  (60,70]  (60,70]  (60,70]  (60,70] 
 [71] (70,80]  (70,80]  (70,80]  (70,80]  (70,80]  (70,80]  (70,80] 
 [78] (70,80]  (70,80]  (70,80]  (80,90]  (80,90]  (80,90]  (80,90] 
 [85] (80,90]  (80,90]  (80,90]  (80,90]  (80,90]  (80,90]  (90,100]
 [92] (90,100] (90,100] (90,100] (90,100] (90,100] (90,100] (90,100]
 [99] (90,100] (90,100]
10 Levels: (0,10] (10,20] (20,30] (30,40] (40,50] (50,60] ... (90,100]
> plot(cut(x, seq(0, 100, 10))) # 绘制图3,使用cut()函数可以对数值型连续性变量进行转化为因子
> state.region # R内置因子型数据
 [1] South         West          West          South        
 [5] West          West          Northeast     South        
...
Levels: Northeast South North Central West
> plot(state.region) # 绘制图4

[photos]

[/photos]

table()&tapply()——针对含有因子类型数据的操作

> state  # state 数据集型对象
                   state.name  state.region state.abb state.area
Alabama               Alabama         South        AL      51609
Alaska                 Alaska          West        AK     589757
Arizona               Arizona          West        AZ     113909
...
> tapply(state.name, state.division, FUN = length) # 第二个参数要填入因子数据(连续型变量)
       New England    Middle Atlantic     South Atlantic 
                 6                  3                  8 
East South Central West South Central East North Central 
                 4                  4                  5 
West North Central           Mountain            Pacific 
                 7                  8                  5 
> table(state.division) # state.division是连续型变量,可以作为因子来操作
state.division
       New England    Middle Atlantic     South Atlantic 
                 6                  3                  8 
East South Central West South Central East North Central 
                 4                  4                  5 
West North Central           Mountain            Pacific 
                 7                  8                  5 

缺失数据

缺失数据分类

统计学家通常将缺失数据分为三类。它们都用概率术语进行描述,但思想都非常直观。我们将用sleep研究中对做梦时长的测量(有12个动物有缺失值)来依次阐述三种类型。

完全随机缺失:若某变量的缺失数据与其他任何观测或未观测变量都不相关,则数据为完全随机缺失(MCAR)。若12个动物的做梦时长值缺失不是由于系统原因,那么可认为数据是(MCAR)。注意,如果每个有缺失值的变量都是MCAR,那么可以将数据完整的实例看做是对更大数据集的一个简单随机抽样。

随机缺失:若某变量上的缺失数据与其他观测变量相关,与它自己的未观测值不相关,则数据为随机缺失(MAR)。例如,体重较小的动物更可能有做梦时长的缺失值(可能因为较小的动物较难观察)“缺失”与动物的做梦时长无关,那么该数据就可以认为是MAR。此时,一旦你控制了体重变量,做梦时长数据的缺失与出现将是随机的。

非随机缺失:若缺失数据不属于MCAR或MAR,则数据为非随机缺失(NMAR)。例如,做梦时长越短的动物也更可能有做梦数据的缺失(可能由于难以测量时长较短的事件),那么数据可认为是NMAR。

为何会出现缺失数据?

  1. 机器断电,设备故障导致某个测量值发生了丢失。
  2. 测量根本没有发生,例如在做调查问卷时,有些问题没有回答,或者有些问题是无效的回答等。

在R中,NA代表缺失值,NA是不可用,not available的简称,用来存储缺失信息。

这里缺失值NA表示没有,但注意没有并不一定就是0,NA是不知道是多少,也能是0,也可能是任何值,缺失值和值为零是完全不同的。

> 1+NA # NA与数值相加仍为NA
[1] NA
> 0 == NA # NA是不等于0
[1] NA
> x <- c(1, NA, 2:10, NA) # 创建一个带有缺失值的数值型变量
> x
 [1]  1 NA  2  3  4  5  6  7  8  9 10 NA
> sum(x) # 元素中含有NA,那么结果中也是NA
[1] NA
> sum(x, na.rm = T) # 计算的时候去除NA
[1] 55
> mean(x)
[1] NA
> mean(x, na.rm = T)
[1] 5.5
> is.na(x) # 判断是否含有NA
 [1] FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE

矩阵中含有缺失值的处理

> library(VIM) # 载入VIM包,需要使用里面的sleep矩阵
> sleep # 一些动物睡眠的数据
    BodyWgt BrainWgt NonD Dream Sleep  Span  Gest Pred Exp Danger
1  6654.000  5712.00   NA    NA   3.3  38.6 645.0    3   5      3
2     1.000     6.60  6.3   2.0   8.3   4.5  42.0    3   1      3
3     3.385    44.50   NA    NA  12.5  14.0  60.0    1   1      1
4     0.920     5.70   NA    NA  16.5    NA  25.0    5   2      3
5  2547.000  4603.00  2.1   1.8   3.9  69.0 624.0    3   5      4
...
> length(sleep) # 显示矩阵的列数
[1] 10
> length(row.names(sleep)) # 显示矩阵的行数
[1] 62
> length(row.names(na.omit(sleep))) # 去除矩阵中含有缺失值的行
[1] 42

R中缺失值得处理方式

其他缺失数据

  1. 缺失数据NaN代表不可能的值;
  2. Inf表示无穷,分为正无穷Inf和负无穷Inf,代表无穷大或者无穷小,是不可能的值。
NA是存在的值,但是不知道是多少,
> 1/0
[1] Inf
>  0/0
[1] NaN
> -1/0
[1] -Inf
> is.nan(0/0)
[1] TRUE
> is.infinite(-1/0)
[1] TRUE

字符串

nchar()——字符串长度

> nchar("Hello, world.") # 统计字符串中字符数(字符串的长度),包含标点符号和空格
[1] 13
> month.name # R中内置的一个字符串
 [1] "January"   "February"  "March"     "April"     "May"       "June"      "July"     
 [8] "August"    "September" "October"   "November"  "December" 
> class(month.name) # 它的类型是一个字符串向量
[1] "character"
> nchar(month.name) # 返回字符串向量中每一个字符串的长度
 [1] 7 8 5 5 3 4 4 6 9 7 8 8
> length(month.name) # 返回字符串向量的长度(即内部元素个数)
[1] 12
> length("Hello, world.") # 返回元素个数
[1] 1
> nchar(1:10) # 对数值型向量使用,会默认将每一个数值转化为字符串,再查看字符个数
 [1] 1 1 1 1 1 1 1 1 1 2

paste()——粘合字符串

> x <- c("Everybody", "Loves", "Money") # 创建一个字符串向量x
> paste("Everybody", "Loves", "Money") # 将几个字符串变量合并为一个字符串(默认的分隔符是空格)
[1] "Everybody Loves Money"
> paste("Everybody", "Loves", "Money", sep = "-") # sep参数更改默认分隔符
[1] "Everybody-Loves-Money"
> paste(x, "1111", "2222", sep = "_") # 一个举例
[1] "Everybody_1111_2222" "Loves_1111_2222"     "Money_1111_2222"   

substr()——截取字符串

 > substr(month.name, start = 1, stop = 3) # 截取字符串向量中每个元素的前三位
 [1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"
> substr(month.name, 1, 3)
 [1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"

toupper(), tolower()——字符串的大小写转换

> toupper(substr(month.name, 1, 3))
 [1] "JAN" "FEB" "MAR" "APR" "MAY" "JUN" "JUL" "AUG" "SEP" "OCT" "NOV" "DEC"
> tolower(substr(month.name, 1, 3))
 [1] "jan" "feb" "mar" "apr" "may" "jun" "jul" "aug" "sep" "oct" "nov" "dec"

gsub()——R中正则表达式的使用

> ?gsub()
> gsub("^(\\w)", "\\U\\1", tolower(month.name), perl = T)
 [1] "January"   "February"  "March"     "April"     "May"       "June"      "July"     
 [8] "August"    "September" "October"   "November"  "December" 
> gsub("^(\\w)", "\\U\\1", substr(tolower(month.name), 1, 3), perl = T)
 [1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"

grep(), match()——查找字符串中的元素

> x <- c("b", "A", "ABC", "asasABC")
> grep("A+", x)
[1] 2 3 4
> grep("A+", x, fixed = T)
integer(0)
> grep("A+", x, fixed = F)
[1] 2 3 4
> x <- c("b", "A", "ABC", "asasABC", "A+")
> grep("A+", x, fixed = T)
[1] 5
> match("A", x)
[1] 2
>  "A" %in% x
[1] TRUE

strsplit()——拆分字符串

> z <- paste("Everybody", "Loves", "Money", sep = "_") # 创建一个字符串向量
> z
[1] "Everybody_Loves_Money"
> strsplit(z, "_") # 分解字符串向量, 注意:分解出来的是列表对象([[]]),并不是向量
[[1]]
[1] "Everybody" "Loves"     "Money"    

> 
> strsplit(z, "_")[[1]] # 取出列表中的向量
[1] "Everybody" "Loves"     "Money"    
> class(strsplit(z, "_"))
[1] "list"

> strsplit(c(z, z), "_") # 这一步就可以解释为什么分解出来的是列表对象了,因为该函数可以同时分解多个字符串
[[1]]
[1] "Everybody" "Loves"     "Money"    

[[2]]
[1] "Everybody" "Loves"     "Money"   

outer()——解释起来很麻烦,自己看例子

> face <- 1:13 # 创建一个数值型向量(代表扑克牌1到13)
> suit <- c("spades", "clubs", "hearts", "diamonds") # 创建一个字符串变量(代表扑克牌的4中花色)
> outer(suit, face, FUN = paste, sep = "_") # 对扑克牌的数字与花色进行一一拼装(sep默认为空格),返回的是一个矩阵对象
     [,1]         [,2]         [,3]         [,4]         [,5]         [,6]        
[1,] "spades_1"   "spades_2"   "spades_3"   "spades_4"   "spades_5"   "spades_6"  
[2,] "clubs_1"    "clubs_2"    "clubs_3"    "clubs_4"    "clubs_5"    "clubs_6"   
[3,] "hearts_1"   "hearts_2"   "hearts_3"   "hearts_4"   "hearts_5"   "hearts_6"  
[4,] "diamonds_1" "diamonds_2" "diamonds_3" "diamonds_4" "diamonds_5" "diamonds_6"
     [,7]         [,8]         [,9]         [,10]         [,11]         [,12]        
[1,] "spades_7"   "spades_8"   "spades_9"   "spades_10"   "spades_11"   "spades_12"  
[2,] "clubs_7"    "clubs_8"    "clubs_9"    "clubs_10"    "clubs_11"    "clubs_12"   
[3,] "hearts_7"   "hearts_8"   "hearts_9"   "hearts_10"   "hearts_11"   "hearts_12"  
[4,] "diamonds_7" "diamonds_8" "diamonds_9" "diamonds_10" "diamonds_11" "diamonds_12"
     [,13]        
[1,] "spades_13"  
[2,] "clubs_13"   
[3,] "hearts_13"  
[4,] "diamonds_13"

R界大佬:Hadley Wickham

日期和时间

  1. 对时间序列的描述;
  2. 利用前面的结果进行预测。

R中专门处理时间和日期的包:TimeSeries(中科大镜像)。

> sunspots # R内置太阳黑子数据
       Jan   Feb   Mar   Apr   May   Jun   Jul   Aug   Sep   Oct   Nov   Dec
1749  58.0  62.6  70.0  55.7  85.0  83.5  94.8  66.3  75.9  75.5 158.6  85.2
1750  73.3  75.9  89.2  88.3  90.0 100.0  85.4 103.0  91.2  65.7  63.3  75.4
1751  70.0  43.5  45.3  56.4  60.7  50.7  66.3  59.8  23.5  23.2  28.5  44.0
 [ reached getOption("max.print") -- omitted 152 rows ]
> presidents # R内置总统支持率数据
     Qtr1 Qtr2 Qtr3 Qtr4
1945   NA   87   82   75
1946   63   50   43   32
1947   35   60   54   55
...
> class(sunspots) # 两者的数据类型都是时间序列
[1] "ts"
> class(presidents)
[1] "ts"
> airquality # R内置空气质量数据
    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
...
> class(airquality) # 该数据的类型时数据框
[1] "data.frame"
> airquality$Wind # 数据框型数据可以使用$进行访问
  [1]  7.4  8.0 12.6 11.5 14.3 14.9  8.6 13.8 20.1  8.6  6.9  9.7  9.2 10.9 13.2 11.5 12.0
...

Sys.Date()——显示当前系统日期

> Sys.Date() # 显示当前时间
[1] "2022-04-16"
> class(Sys.Date())
[1] "Date"

as.Date()——将字符串转换为时间类型数据

> date_time <- "2022-04-16" # 创建一个字符串
> as.Date(date_time, format = "%Y-%m-%d") # 将字符串转换为时间格式数据
[1] "2022-04-16"
> class(as.Date(date_time, format = "%Y-%m-%d"))
[1] "Date"
> class(date_time)
[1] "character"
> ?strftime
> seq(as.Date("2022-01-01"), as.Date("2022-04-16"), by=5) # 创建一个时间序列
 [1] "2022-01-01" "2022-01-06" "2022-01-11" "2022-01-16" "2022-01-21" "2022-01-26"
 [7] "2022-01-31" "2022-02-05" "2022-02-10" "2022-02-15" "2022-02-20" "2022-02-25"
[13] "2022-03-02" "2022-03-07" "2022-03-12" "2022-03-17" "2022-03-22" "2022-03-27"
[19] "2022-04-01" "2022-04-06" "2022-04-11" "2022-04-16"
> class(as.Date("2022-01-01"))
[1] "Date"
> as.Date("2022-01-01")
[1] "2022-01-01"
> class(as.Date(date_time))
[1] "Date"
> as.Date("2022_01_01")
Error in charToDate(x) : 字符串的格式不够标准明确
> as.Date("2022_01_01", format = "%Y_%m_%d")
[1] "2022-01-01"

ts()——生成时间序列

> ?ts
> sales <- round(runif(48, min = 50, max = 100)) # 生成一个随机整数数值序列
> sales
 [1] 89 65 93 85 96 55 59 76 51 52 95 70 75 80 88 59 73 85 81 73 61 81 86 91 71 80
[27] 73 96 58 81 66 78 71 51 64 85 81 75 95 58 99 97 63 88 70 64 79 72
> ts(sales, start = c(2010, 5), end = c(2014, 4), frequency = 12) # 参数为12时,以月份为频率
     Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
2010                  89  65  93  85  96  55  59  76
2011  51  52  95  70  75  80  88  59  73  85  81  73
2012  61  81  86  91  71  80  73  96  58  81  66  78
2013  71  51  64  85  81  75  95  58  99  97  63  88
2014  70  64  79  72                                
> ts(sales, start = c(2010, 5), end = c(2014, 4), frequency = 4) # 参数为4时,以季度为频率
     Qtr1 Qtr2 Qtr3 Qtr4
2011   89   65   93   85
2012   96   55   59   76
2013   51   52   95   70
2014   75   80   88   59
> ts(sales, start = c(2010, 5), end = c(2014, 4), frequency = 1) # 参数为1时,以年为频率
Time Series:
Start = 2014 
End = 2017 
Frequency = 1 
[1] 89 65 93 85

获取数据

获取途径

  1. 利用键盘来输入数据;
  2. 通过读取存储在外部文件上的数据;
  3. 通过访问数据库系统来获取数据。

键盘输入(看看就行,谁用谁SB)

> patientID <- c(1, 2, 3, 4) # 创建数据
> admdate <- c("10/15/2009","11/01/2009","10/21/2009","10/28/2009")
> age <- c(25, 34, 28, 52)
> diabetes <- c("Type1", "Type2", "Type1", "Type1")
> status <- c("Poor", "Improved", "Excellent", "Poor")
> patient_data <- data.frame(patientID, admdate, age, diabetes, status)
> patient_data
  patientID    admdate age diabetes    status
1         1 10/15/2009  25    Type1      Poor
2         2 11/01/2009  34    Type2  Improved
3         3 10/21/2009  28    Type1 Excellent
4         4 10/28/2009  52    Type1      Poor
> admdate_ts <- as.Date(admdate, format = "%m/%d/%Y") # 将admdate数据转化为时间序列,方便后续操作
> patient_data_2 <- data.frame(patientID, admdate_ts, age, diabetes, status) # 这个是升级版,时间不再是字符串,而是Date格式数据
> patient_data_2
  patientID admdate_ts age diabetes    status
1         1 2009-10-15  25    Type1      Poor
2         2 2009-11-01  34    Type2  Improved
3         3 2009-10-21  28    Type1 Excellent
4         4 2009-10-28  52    Type1      Poor
> class(patient_data_2$admdate_ts)
[1] "Date"

read()——读取文件(重点)

> getwd() # 读取文件之前可以先查看下R的工作目录
[1] "C:/Users/myxc/Documents"
> setwd("D:/R") # 设置R的工作目录
> getwd() # 查看R的工作目录已经被修改
[1] "D:/R"
> date_demo <- read.table("./RData/input.txt") # 读取txt文件
> date_demo
    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
...
> head(date_demo) # 查看读取数据框的前五行
  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
> tail(date_demo) # 查看读取数据框的后五行
    Ozone Solar.R Wind Temp Month Day
148    14      20 16.6   63     9  25
149    30     193  6.9   70     9  26
150    NA     145 13.2   77     9  27
151    14     191 14.3   75     9  28
152    18     131  8.0   76     9  29
153    20     223 11.5   68     9  30
> head(date_demo, n = 10) # 查看读取数据框的前10行
   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
7     23     299  8.6   65     5   7
8     19      99 13.8   59     5   8
9      8      19 20.1   61     5   9
10    NA     194  8.6   69     5  10

几个参数注意下:

查看帮助

> help(package="foreign")

> RSiteSearch("Origin") # 使用在线搜索来满足你足够变态的需求
A search query has been submitted to http://search.r-project.org
计算结果应很快就在瀏覽器里打开

读取剪切板

x <- read.table("clipboard") # 方法一
x <- readClipboard() # 方法二

读取压缩文件

x <- read.table(gzfile("input.txt.gz"))

数据库

谁爱学谁学,反正我不学。

写入文件

写入文件的包

> help(package="foreign")

常用的几个命令

> ?write # 写入文件使用的函数
> rivers # R中自带的一个数值型向量
  [1]  735  320  325  392  524  450 1459  135  465  600  330  336  280  315  870
...
> class(rivers)
[1] "numeric"
> cat(rivers) # 该函数直接将要写入的文件显示在终端里
735 320 325 392 524 450 1459 135 465 600 330 336 280 315 870 906 202 329 290 1000 600 505 1450 840 ...
> getwd() # 查看R工作目录
[1] "C:/Users/myxc/Documents"
> setwd("D:/R")
> getwd()
[1] "D:/R"
> write(rivers, file = "demo.txt", ncolumns = 10,sep = "-") # 写入文件,一行10个元素,每行元素之间的分隔符为“-”(默认为空格)
> # 注意:R不会创建新的目录
> table_demo <- read.table("./RData/input.txt", header = T)
> head(table_demo)
  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
> write.table(table_demo, "./new_input.txt") # 写入文件
> write.table(table_demo, "./new_input.csv", sep = ",") # 写入文件,每一行的分隔符使用“,”
> write.table(table_demo, "./new_input.csv", sep = ",", row.names = F) # 写入文件时不要R添加序号
> write.table(table_demo, "./new_input.txt", quote = F) # 写入文件时,去掉每一个变量的引号
> write.table(table_demo, "./new_input.txt", quote = F, na = "?") # 写入的时候NA值用其他代替
> write.table(mtcars, gzfile("mtcars.txt.gz")) # 写入文件直接压缩

写入Excel文件

这一节就是辣鸡,我用个R还要装个Java环境?脱裤子放屁,Python真香!

> install.packages("XLConnect") # R中操作xlsx文件的包(需要Java环境)
> library(XLConnect) # 载入包
> excelTable <- loadWorkbook("./RData/data.xlsx") # 打开xlsx文件
> readWordsheet(excelTable, 1) # 读取文件中的第一个表

#Two step Read Excel File
ex <- loadWorkbook ("data.xlsx")
edata <- readWorksheet(ex,1)
head(edata)
edata <- readWorksheet(ex,1,startRow=0,starCol=0,endRow=50,endCol=3)

#One step Read Excel File
readWorksheetFromFile ("data.xlsx",1,startRow=0,starCol=0,
                       endRow=50,endCol=3,header=TRUE)
#Four step Wtire Excel File
wb <- loadWorkbook("file.xlsx",create=TRUE)
createSheet(wb,"Sheet 1")
writeWorksheet(wb,data=mtcars,sheet = "Sheet 1")
saveWorkbook()

#One step Wtire Excel File
writeWorksheetToFile("file.xlsx",data = mtcars,sheet = "Sheet 1")
vignette("XLConnect")

#Packages xlsx
install.packages("xlsx")
library(xlsx)
rdata <- read.xlsx("data.xlsx",n=1,startRow = 1,endRow = 100)
write.xlsx(rdata,file = "rdata.xlsx",sheetName = "Sheet 1",append = F)
help(package="xlsx")

读写R格式文件

存储为R文件会有很多优势,R会对存储为内部文件格式的数据进行自动压缩处理,并且会存储所有与待存储对象相关的R元数据。如果数据中包含了因子,日期和时间或者类的属性等信息。

> saveRDS(iris, "./demo.RDS") # 保存R中的变量到R专用的数据格式中
> getwd()
[1] "D:/R"
> input_iris <- readRDS("./demo.RDS") # 读取保存的变量
> head(input_iris) # 和原来的一毛一样
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa
> load("./RData/.RData") # 加载R文件
> save(iris, iris3, file = "c:/Users/myxc/Desktop/demo.Rdata") # 保存R工程文件
> save.image() # 保存当前R工程文件

数据转换

> mtcars
                     mpg cyl  disp  hp drat    wt  qsec vs am gear
Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4
Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4
Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4
...
> is.data.frame(mtcars) # 判断数据是否为数据框类型
[1] TRUE
> state.x77
               Population Income Illiteracy Life Exp Murder
Alabama              3615   3624        2.1    69.05   15.1
Alaska                365   6315        1.5    69.31   11.3
Arizona              2212   4530        1.8    70.55    7.8
...
> is.data.frame(state.x77) # 判断数据是否为数据框类型
[1] FALSE
> is.data.frame(as.data.frame(state.x77)) # 强制转换数据类型
[1] TRUE
> is.data.frame(data.frame(state.x77))
[1] TRUE
> as.matrix(data.frame(state.x77, state.region))
               Population Income Illiteracy Life.Exp Murder
Alabama        " 3615"    "3624" "2.1"      "69.05"  "15.1"
Alaska         "  365"    "6315" "1.5"      "69.31"  "11.3"
Arizona        " 2212"    "4530" "1.8"      "70.55"  " 7.8"
...  
> methods(is)
 [1] is.array                is.atomic              
 [3] is.call                 is.character           
...      
see '?methods' for accessing help and source code
Warning message:
In .S3methods(generic.function, class, envir) :
  function 'is' appears not to be S3 generic; found functions that look like S3 methods
> methods(s3)
Error in methods(s3) : object 's3' not found
> methods(is)
 [1] is.array                is.atomic              
 [3] is.call                 is.character           
...    
see '?methods' for accessing help and source code
Warning message:
In .S3methods(generic.function, class, envir) :
  function 'is' appears not to be S3 generic; found functions that look like S3 methods
> methods(as)
  [1] as.array                      as.array.default             
  [3] as.call                       as.character                 
  [5] as.character.condition        as.character.Date            
...
see '?methods' for accessing help and source code
Warning message:
In .S3methods(generic.function, class, envir) :
  function 'as' appears not to be S3 generic; found functions that look like S3 methods
> x <- state.abb
> x
 [1] "AL" "AK" "AZ" "AR" "CA" "CO" "CT" "DE" "FL" "GA" "HI" "ID"
..
> dim(x) <- c(5, 10)
> x
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] "AL" "CO" "HI" "KS" "MA" "MT" "NM" "OK" "SD" "VA" 
...
> state_demo <- data.frame(state.region, state.x77)
> state_demo$Income
 [1] 3624 6315 4530 3378 5114 4884 5348 4809 4815 4091 4963 4119
...
> unname(state["Nevada", ]) # 不显示数据框的表头
                                                               
Nevada Nevada West NV 110540 -116.851 39.1063 Mountain 590 5149
                                     
Nevada 0.5 69.03 11.5 65.2 188 109889

数据的中心化与标准化

数据中心化,是指数据集中的各项数据减去数据集的均值。

数据标准化,是指在中心化之后在除以数据集的标准差,即数据集中的各项数据减去数据集的均值再除以数据集的标准差。

中心化与标准化的目的就是为了让一组数据更加地向中心靠拢。

参考网络链接:数据什么时候需要做中心化和标准化处理?

举个例子

> state.x77 # 数据框型&矩阵型对象(有行列名称,可以绘制热图)
               Population Income Illiteracy Life Exp Murder
Alabama              3615   3624        2.1    69.05   15.1
Alaska                365   6315        1.5    69.31   11.3
Arizona              2212   4530        1.8    70.55    7.8
...
> heatmap(state.x77)

但是可以看出,state.x77[,'Population']state.x77[,'Income']state.x77[,'Illiteracy']等列的数据差值是很大的,如果这个时候进行热图的绘制并没有什么意义,绘制出来的图形颜色对比太模糊。

出现这种情况,我们就要对数据进行中心化与标准化,先讲解下其基本流程:

> x <- c(1:6)  # 创建一个数值型向量
> x
[1] 1 2 3 4 5 6
> x_mean <- x-mean(x)  # 计算向量x的平均值,然后用向量x中的每个元素都减去平均值
> x_mean  # 如果发现这个时候新的向量差值还是很大,那么就可以再次计算标准差
[1] -2.5 -1.5 -0.5  0.5  1.5  2.5
> x_sd <- x_mean/sd(x)  # 经历了除以标准差之后,数据之间的差异性就明显减小了,更加收拢。
> x_sd
[1] -1.3363062 -0.8017837 -0.2672612  0.2672612  0.8017837
[6]  1.3363062

scale()——直接进行中心化与标准化

> scale(x)
           [,1]
[1,] -1.3363062
[2,] -0.8017837
[3,] -0.2672612
[4,]  0.2672612
[5,]  0.8017837
[6,]  1.3363062
attr(,"scaled:center")
[1] 3.5
attr(,"scaled:scale")
[1] 1.870829
> class(scale(x))
[1] "matrix" "array" 
> mean(x)
[1] 3.5
> sd(x)
[1] 1.870829
> scale(x, center = T, scale = T)
           [,1]
[1,] -1.3363062
[2,] -0.8017837
[3,] -0.2672612
[4,]  0.2672612
[5,]  0.8017837
[6,]  1.3363062
attr(,"scaled:center")
[1] 3.5
attr(,"scaled:scale")
[1] 1.870829
> ?scale
> scale(state.x77)  # 进行中心化与标准化
                Population      Income Illiteracy     Life Exp
Alabama        -0.14143156 -1.32113867   1.525758 -1.362193670
Alaska         -0.86939802  3.05824562   0.541398 -1.168509784
Arizona        -0.45568908  0.15330286   1.033578 -0.244786635
...
attr(,"scaled:center")
Population     Income Illiteracy   Life Exp     Murder    HS Grad 
 4246.4200  4435.8000     1.1700    70.8786     7.3780    53.1080 
     Frost       Area 
  104.4600 70735.8800 
attr(,"scaled:scale")
  Population       Income   Illiteracy     Life Exp       Murder 
4.464491e+03 6.144699e+02 6.095331e-01 1.342394e+00 3.691540e+00 
     HS Grad        Frost         Area 
8.076998e+00 5.198085e+01 8.532730e+04 
> heatmap(scale(state.x77))

经过中心化与标准化再绘制的热图就非常具有对比性,每一列数据的差异性都得到了很好的提现。

几个包的学习

reshape2()

这人讲的太拉了,好歹也是学过好几门编程语言的人,听的迷迷糊糊,看评论好多也都说不行的。
> install.packages("reshape2")  # 安装包
> library(reshape2)  #  载入包
> class(airquality) # 查看airquality数据框
[1] "data.frame"
> 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
> names(airquality) <- tolower(names(airquality)) # 将数据框的列名称全部变成小写
> head(airquality)
  ozone solar.r wind temp month day
1    41     190  7.4   67     5   1
...
> melt(airquality)  # 会将数据框“融化”
    variable value
1      ozone  41.0
2      ozone  36.0
...
154  solar.r 190.0
155  solar.r 118.0
...
307     wind   7.4
308     wind   8.0
...
460     temp  67.0
461     temp  72.0
... #  后面还会有 month、day等,将一个数据框中的数据全部“融化”成一个个单元格
> class(aql) # 还是数据框格式
[1] "data.frame"
> melt(airquality, id.vars = c("month"))  # 固定month这一列,然后将其他单元格全部“融化”
    month variable value
1       5    ozone  41.0
2       5    ozone  36.0
...
154     5  solar.r 190.0
155     5  solar.r 118.0
...
307     5     wind   7.4
308     5     wind   8.0
...
 [ reached 'max' / getOption("max.print") -- omitted 432 rows ]
> dcast(aql, month, ~variable)  # 根本没看懂~ 讲的是个啥东西!
Error in is.formula(formula) : object 'month' not found
> dcast(aql, month ~variable)
Error in FUN(X[[i]], ...) : object 'month' not found
> dcast(aql, month+day ~variable)
Error in FUN(X[[i]], ...) : object 'month' not found

tidyr()

> install.packages("tidyr")  # 安装包
> library(tidyr)  # 载入包
> head(mtcars)
                   mpg cyl disp  hp drat    wt  qsec vs am gear
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4
...
> class(mtcars)
[1] "data.frame"
> mtcars[1:10,1:3] # 截取mtcar数据框中1~10行,1~3列的元素
                   mpg cyl  disp
Mazda RX4         21.0   6 160.0
Mazda RX4 Wag     21.0   6 160.0
Datsun 710        22.8   4 108.0
Hornet 4 Drive    21.4   6 258.0
Hornet Sportabout 18.7   8 360.0
Valiant           18.1   6 225.0
Duster 360        14.3   8 360.0
Merc 240D         24.4   4 146.7
Merc 230          22.8   4 140.8
Merc 280          19.2   6 167.6
> tdata <- mtcars[1:10,1:3]
> tdata <- data.frame(name=rownames(tdata),tdata)  # 将tdata中的行名称添加到数据框中作为一列
> tdata
                               name  mpg cyl  disp
Mazda RX4                 Mazda RX4 21.0   6 160.0
Mazda RX4 Wag         Mazda RX4 Wag 21.0   6 160.0
Datsun 710               Datsun 710 22.8   4 108.0
Hornet 4 Drive       Hornet 4 Drive 21.4   6 258.0
Hornet Sportabout Hornet Sportabout 18.7   8 360.0
Valiant                     Valiant 18.1   6 225.0
Duster 360               Duster 360 14.3   8 360.0
Merc 240D                 Merc 240D 24.4   4 146.7
Merc 230                   Merc 230 22.8   4 140.8
Merc 280                   Merc 280 19.2   6 167.6
> gather(tdata,key = "Key",value = "Value",cyl,disp,mpg)  # 和resharp2中的merge()差不多
                name  Key Value
1          Mazda RX4  cyl   6.0
2      Mazda RX4 Wag  cyl   6.0
...
11         Mazda RX4 disp 160.0
12     Mazda RX4 Wag disp 160.0
...
21         Mazda RX4  mpg  21.0
22     Mazda RX4 Wag  mpg  21.0
...
> gather(tdata,key = "Key",value = "Value",cyl:disp)  # “融化”cyl:disp两列,扔掉了disp列
                name  mpg  Key Value
1          Mazda RX4 21.0  cyl   6.0
2      Mazda RX4 Wag 21.0  cyl   6.0
..
11         Mazda RX4 21.0 disp 160.0
12     Mazda RX4 Wag 21.0 disp 160.0
...
> gather(tdata,key = "Key",value = "Value",cyl:disp, mpg)  # 和第一步一样的
                name  Key Value
1          Mazda RX4  cyl   6.0
...
11         Mazda RX4 disp 160.0
...
21         Mazda RX4  mpg  21.0
...
> gather(tdata,key = "Key",value = "Value",mpg,cyl,-disp) # “融化”mpg,cyl两列,不管disp这一列,但是不扔掉,和上面的有所区别
                name  disp Key Value
1          Mazda RX4 160.0 mpg  21.0
2      Mazda RX4 Wag 160.0 mpg  21.0
...
11         Mazda RX4 160.0 cyl   6.0
12     Mazda RX4 Wag 160.0 cyl   6.0
...
> gdata <- gather(tdata,key = "Key",value = "Value",cyl,disp,mpg) # 三列完全“融化”
> spread(gdata,key = "Key",value = "Value")  # 合并,上一步的反向操作
                name cyl  disp  mpg
1         Datsun 710   4 108.0 22.8
2         Duster 360   8 360.0 14.3
...

# 拆分或者合并某一列
> df <- data.frame(x = c(NA, "a.b", "a.d", "b.c"))
> df
     x
1 <NA>
2  a.b
3  a.d
4  b.c
> separate(df,col=x,into = c("A","B")) # 拆分
     A    B
1 <NA> <NA>
2    a    b
3    a    d
4    b    c
> separate(df,col=x,into = c("A","B"))
     A    B
1 <NA> <NA>
2    a    b
3    a    d
4    b    c
> df <- data.frame(x = c(NA, "a.b-c", "a-d", "b-c"))
> separate(df,x,into = c("A","B"),sep = "-")
     A    B
1 <NA> <NA>
2  a.b    c
3    a    d
4    b    c
> x <- separate(df,x,into = c("A","B"),sep = "-") # 合并
> unite(x,col ="AB",A,B,sep="-")
     AB
1 NA-NA
2 a.b-c
3   a-d
4   b-c

dplyr()

> library(dplyr) # 载入包
> ls("package:dplyr")  # 查看包内的方法
> dplyr::filter(iris,Sepal.Length>7.8)  # 过滤出iris数据框中Sepal.Length>7.8的行数据
  Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
1          7.9         3.8          6.4           2 virginica
> dplyr::distinct(rbind(iris[1:5,],iris[1:3,]))  # 去除重复行
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
> dplyr::slice(iris,11:15)  # 对矩阵进行切片,选择任意行
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.4         3.7          1.5         0.2  setosa
2          4.8         3.4          1.6         0.2  setosa
3          4.8         3.0          1.4         0.1  setosa
4          4.3         3.0          1.1         0.1  setosa
5          5.8         4.0          1.2         0.2  setosa
> iris %>% head(15) %>% tail(5)  # 等于这种效果,但是行索引不一样
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
11          5.4         3.7          1.5         0.2  setosa
12          4.8         3.4          1.6         0.2  setosa
13          4.8         3.0          1.4         0.1  setosa
14          4.3         3.0          1.1         0.1  setosa
15          5.8         4.0          1.2         0.2  setosa
> dplyr::sample_n(iris,2)
  Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
1          5.1         3.4          1.5         0.2     setosa
2          6.7         3.1          4.4         1.4 versicolor
> dplyr::sample_n(iris,2)  # 从一个矩阵里随机选出两列
  Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
1          5.9         3.0          5.1         1.8  virginica
2          6.3         2.5          4.9         1.5 versicolor
> dplyr::sample_frac(iris,0.01)  # 从一个矩阵里随机选出1%的行
  Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
1          5.9         3.0          5.1         1.8 virginica
2          5.4         3.4          1.7         0.2    setosa
> dplyr::sample_frac(iris,0.01)
  Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
1          6.6           3          4.4         1.4 versicolor
2          6.5           3          5.2         2.0  virginica
> head(dplyr::arrange(iris,Sepal.Length))  # 对数据框iris中的元素按照Sepal.Length进行排序
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          4.3         3.0          1.1         0.1  setosa
2          4.4         2.9          1.4         0.2  setosa
3          4.4         3.0          1.3         0.2  setosa
4          4.4         3.2          1.3         0.2  setosa
5          4.5         2.3          1.3         0.3  setosa
6          4.6         3.1          1.5         0.2  setosa
> iris %>% dplyr::arrange(Sepal.Length) %>% head()  # 等于上一步
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          4.3         3.0          1.1         0.1  setosa
2          4.4         2.9          1.4         0.2  setosa
3          4.4         3.0          1.3         0.2  setosa
4          4.4         3.2          1.3         0.2  setosa
5          4.5         2.3          1.3         0.3  setosa
6          4.6         3.1          1.5         0.2  setosa
> dplyr::arrange(iris,desc(Sepal.Length)) %>% head()  # 使用desc()函数进行逆序
  Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
1          7.9         3.8          6.4         2.0 virginica
2          7.7         3.8          6.7         2.2 virginica
3          7.7         2.6          6.9         2.3 virginica
4          7.7         2.8          6.7         2.0 virginica
5          7.7         3.0          6.1         2.3 virginica
6          7.6         3.0          6.6         2.1 virginica
> summarise(iris,avg=mean(Sepal.Length))  # 求Sepal.Length列的平均值,返回的是一个数据集对象
avg
1 5.843333
> mean(iris$Sepal.Length)  # 返回的是一个数字
[1] 5.843333
> summarise(iris,sum=sum(Sepal.Length))
    sum
1 876.5
> iris %>% dplyr::group_by(Species) %>% summarise(sum=sum(Sepal.Length)) # 将iris数据集按照Species列分类,然后计算每一类的Sepal.Length的和
# A tibble: 3 x 2
  Species      sum
  <fct>      <dbl>
1 setosa      250.
2 versicolor  297.
3 virginica   329.
> iris %>% group_by(Species) %>% summarise(avg=mean(Sepal.Width)) %>% arrange(avg) # 将iris数据集按照Species列分类,然后计算每一类的Sepal.Width的平均值,然后对其按照平均值排序(终于感受到R语言的牛逼之处了!!!)
# A tibble: 3 x 2
  Species      avg
  <fct>      <dbl>
1 versicolor  2.77
2 virginica   2.97
3 setosa      3.43
> iris %>% dplyr::mutate(new=Sepal.Length+Petal.Length) %>% head(3)  # 对iris数据框新加一列(列名称为new,值为Length+Petal.Length)
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species new
1          5.1         3.5          1.4         0.2  setosa 6.5
2          4.9         3.0          1.4         0.2  setosa 6.3
3          4.7         3.2          1.3         0.2  setosa 6.0
两个表的链接
> a=data.frame(x1=c("A","B","C"),x2=c(1,2,3))  # 创建两个数据框
> b=data.frame(x1=c("A","B","D"),x3=c(T,F,T))
> dplyr::left_join(a,b,by="x1")  # 左连接
  x1 x2    x3
1  A  1  TRUE
2  B  2 FALSE
3  C  3    NA
> dplyr::right_join(a,b,by="x1")  # 右连接
  x1 x2    x3
1  A  1  TRUE
2  B  2 FALSE
3  D NA  TRUE
> dplyr::full_join(a,b,by="x1") # 全连接
  x1 x2    x3
1  A  1  TRUE
2  B  2 FALSE
3  C  3    NA
4  D NA  TRUE
> dplyr::semi_join(a,b,by="x1") # 求交集
  x1 x2
1  A  1
2  B  2
> dplyr::semi_join(b,a,by="x1") # 求交集
  x1    x3
1  A  TRUE
2  B FALSE
> dplyr::anti_join(a,b,by="x1") # 求补集
  x1 x2
1  C  3
> dplyr::anti_join(b,a,by="x1") # 求补集
  x1   x3
1  D TRUE
> first <- mtcars %>% dplyr::mutate(Model = row.names(mtcars)) %>% slice(1:2)
> second <- mtcars %>% dplyr::mutate(Model = row.names(mtcars)) %>% slice(1:3)
> intersect(first, second)  # 求交集
              mpg cyl disp  hp drat    wt  qsec vs am gear carb
Mazda RX4      21   6  160 110  3.9 2.620 16.46  0  1    4    4
Mazda RX4 Wag  21   6  160 110  3.9 2.875 17.02  0  1    4    4
                      Model
Mazda RX4         Mazda RX4
Mazda RX4 Wag Mazda RX4 Wag
> union_all(first, second)  # 求并集
                   mpg cyl disp  hp drat    wt  qsec vs am gear
Mazda RX4...1     21.0   6  160 110 3.90 2.620 16.46  0  1    4
Mazda RX4 Wag...2 21.0   6  160 110 3.90 2.875 17.02  0  1    4
Mazda RX4...3     21.0   6  160 110 3.90 2.620 16.46  0  1    4
Mazda RX4 Wag...4 21.0   6  160 110 3.90 2.875 17.02  0  1    4
Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4
                  carb         Model
Mazda RX4...1        4     Mazda RX4
Mazda RX4 Wag...2    4 Mazda RX4 Wag
Mazda RX4...3        4     Mazda RX4
Mazda RX4 Wag...4    4 Mazda RX4 Wag
Datsun 710           1    Datsun 710

链式操作符% > %,两个百分号中间夹着一个大于号 ,称为链式操作符,它功能是用于实现将一个函数的输出传递给下一个函数,作为下一个函数的输入。在RStudio中可以使用ctrl+shift+M快捷键输出出来。

R函数

参数选项

  1. 输入控制部分;
  2. 2、输出控制部分;
  3. 调节部分。
讲的是个啥东西呀~,实在是悟不透~

自定义函数

主要包括四部分:函数名称、函数声明、函数参数、函数体。

  1. 函数命令与功能相关;
  2. 可以是字母和数字的组合,但必须是字母开头。

一个小例子:设计一个求偏度与峰度的函数。

偏度(skewness)是统计数据分布偏斜方向和程度的度量,是统计数据分布非对称程度的数字特征。

峰度(peakedness; kurtosis)又称峰态系数。表征概率密度分布曲线在平均值处峰值高低的特征数。

mystats <- function(x,na.omit=FALSE) {
  if(na.omit) 
    x <- x[!is.na(x)]
  m <- mean(x)
  n <- length(x)
  s <- sd(x)
  skew <- sum((x-m^3/s^3))/n
  kurt <- sum((x-m^4/s^4))/n-3
  return(c(n=n,mean=m,stdev=s,skew=skew,kurtosis=kurt))
 }

R中的循环

if条件判断

> score=70;if (score >60 ) {print ("Passwd") } else {print ("Failed")}
[1] "Passwd"
> ifelse( score >60,print ("Passwd"),print ("Failed"))
[1] "Passwd"
[1] "Passwd"

while循环

> i <- 1; while (i <= 3) {
+     i = i+1
+     print("Hello, world.")
+ }
[1] "Hello, world."
[1] "Hello, world."
[1] "Hello, world."

for循环

> for (i in 1:3) {print("Hello, world.")}
[1] "Hello, world."
[1] "Hello, world."
[1] "Hello, world."

switch语句等

绘图函数

绘图系统

  1. 高级绘图:高级绘图是一步到位,可以直接绘制出图;
  2. 低级绘图:而低级绘图,不能单独使用,必须在高级绘图产生图形的基础上,对图形进行调整,比如加一条线,加上标题文字等。

S3系统

属性

泛型函数

方法

报错记录

安装报错

> install.packages("VIM")
WARNING: Rtools is required to build R packages but is not currently installed. Please download and install the appropriate version of Rtools before proceeding:

当安装R包的时候显示这个,是提示需要安装Rtools。官网链接:https://cran.r-project.org/bin/windows/Rtools/,需要按照自己的R版本来安装对应的Rtools。

安装过程一路回车即可,默认安装。安装完成之后,运行以下代码,不报错说明安装成功。

> writeLines('PATH="${RTOOLS40_HOME}\\usr\\bin;${PATH}"', con = "~/.Renviron")

继续安装包由发现新问题:

> install.packages("VIM")
将程序包安装入‘C:/Users/myxc/Documents/R/win-library/4.1’
(因为‘lib’没有被指定)
还安装相依关系‘DEoptimR’, ‘proxy’, ‘robustbase’, ‘vcd’, ‘e1071’, ‘laeken’, ‘ranger’, ‘data.table’
...
package ‘DEoptimR’ successfully unpacked and MD5 sums checked
Error in install.packages : ERROR: failed to lock directory ‘C:\Users\myxc\Documents\R\win-library\4.1’ for modifying
Try removing ‘C:\Users\myxc\Documents\R\win-library\4.1/00LOCK’

最后一句提示让删除某个文件夹试试,好家伙,试试就试试。

把上面的文件夹删除了,真就可以成功安装了。

已经可以成功载入安装的包了。

> library(VIM)
载入需要的程辑包:colorspace
载入需要的程辑包:grid
VIM is ready to use.

Suggestions and bug-reports can be submitted at: https://github.com/statistikat/VIM/issues

载入程辑包:‘VIM’

The following object is masked from ‘package:datasets’:

    sleep

当前页面是本站的「Google AMP」版。查看和发表评论请点击:完整版 »