常用机为Mac,但window也是一样的哦(有差别的地方有讲解)
R语言和其他语言差别很大哦,里面有很多基础基础基础的内容,包括介绍数据结构。但语法还是和其他语言一样哦,比如循环、判断。有基础食用更香!
本章单纯为R基础,R的应用与高级操作不属于本章内容
R常被用于做数据分析,通过大数据计算预期的结果
过程:
然后来稍微的介绍一下数据挖掘:
再来讲一下数据可视化:
将数字结果用图展示出来
因为数据是给机器看的,数据可视化是给人看的
了解R语言:
R的优点:和python一样,开源,方法多,拓展性强
R的作用:计算、算法、绘图、编程
R的缺点:什么都能做但复杂,包太多难学
我先给大家来罗列一些常用的系统命令吧,这个也挺简单,就不放图啦~
函数名 | 作用 |
---|---|
list.files() / dir() | 查看当前目录下的文件 |
getwd() / setwd() | 查看/设置默认工作区位置 |
save.image() | 保存数据 |
q() | 退出 |
我们平常会对R包进行增删改查的操作,我们可以看一下我们有哪些操作:
函数名 | 作用 |
---|---|
install.package(“name”) / remove.package(“name”) / update.package(“name”) | 安装/卸载/更新name包的内容(更新可以不带参数) |
library() / library(name) / library(help=“name”) | 查看系统中已有的包 / 判断name包是否存在 / 查看包的信息 |
help(package=“name”) | 打开name包的帮助文档 |
ls(“package:name”) | 查看某个包中全部的函数 |
data(package=“name”) | 查看name包中的数据集 |
require(name) / detach(name) | 加载/关闭名为name的包 |
我们在装好了R的包之后,自然常用的就是对象了,然后下面我们罗列一些针对这些对象的增删改查的指令:
函数名 | 作用 |
---|---|
object<-0 / object<<-0 | 为object赋值为0 / 强制赋值,可以强制给全局变量赋值 |
str(object) | 查看object变量的详细内容 |
rm(object) | 删除object变量(可以使用rm(list=ls())的方法删除所有变量) |
ls() / ls.str() / ls(object) | 查看工作区内的所有变量 / 可以看到工作区中每个变量的详细内容 / 判断object是否存在 / |
我们在不会使用包、函数的时候,经常会借助帮助指令查看帮助,得以了解,在这里我也列出几个帮助指令:
函数名 | 作用 |
---|---|
help(package=name) | 打开name包的帮助文档 |
help(funtion) | 打开funtion函数的帮助文档 |
?funtion | 打开funtion函数的帮助文档 |
args(funtion) | 直接在终端中输出函数应输入的参数 |
emample(“function”) | 会在终端中打印出使用案例, 如果是绘图函数也会给出绘图案例 |
demo(function) | 可以返回一些绘制的阳历图 |
vignette(“package”) | 部分package有这个更规范的开发文档 |
??package | 即使不加载包可以搜索到相应的文档 |
help.search(“package”) | 在本地搜索package包的文档 |
apropos(“key”) / apropos(“key”, mod=“function”) | 可以搜索含有key关键字的内容 / 可以限定搜索的结果为函数 |
RSiteSearch(“key”) | 用默认浏览器在官网搜索key关键字 |
我们经常在学习的时候会用到很多的数据,无论是矩阵数据还是列表数据,等等。一遍又一遍的自己创造数据比较浪费时间,所以R内部含有许多数据集,如美国每个州的名字,每个地方的信息,一些汽车的信息,表格数据,等等等等。我们可以方便的使用这些。
我们在命令行中敲两行帮助代码可以查看到我们有的数据集:
> help(package="datasets")
> data()
R主要分成四大数据类型:
R主要的数据结构:
R语言中的向量,是构成其他数据结构的基础,R中的向量,更像其他语言中的数组。所以我们可以把向量认为是用于存储数据型、字符型、逻辑型数据的一维数组。我们统一用函数c来创建向量,如:
> c(1, 2, 3, 4, 5)
> c('a', 'b', 'c', 'd', 'e')
> c(T, F, T, F, T)
同时要注意,向量中每个数据不能出现不同的数据类型,能转换的会自动帮你转换,不能转换的会直接报错(为啥不能不同呢?因为向量是用来计算的:一种类型才能计算咯),总的来说,优先级是:字符串型>数值型>逻辑型(ps:R中的逻辑型为T/F/TRUE/FALSE,必为全大写)。
我们还能用seq函数构造向量,seq函数的优点是可以控制等差差值:
> seq(1, 100, 2) # seq(初值,终值,步长)
[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
[26] 51 53 55 57 59 61 63 65 67 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99
构造向量的时候我们经常也会用到一些重复的操作(输入多个一样的数),这个时候我们就可以用到rep函数了。rep函数可以将一个对象重复多次,然后我们可以将这个结果赋值到对象中。
> x <- rep('a', 5)
> x
[1] "a" "a" "a" "a" "a"
我们可以明显的看出来我们完成了自己的目的。
当然,我们也可以进行这样的操作:
> x <- c(1,2,3,4,5)
> rep(x, 5) # 将向量复制五次
[1] 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1 2
[18] 3 4 5 1 2 3 4 5
也可以进行这样的操作:
> x <- c(1,2,3,4,5)
> rep(x, each=5) # 将每个元素复制五次
[1] 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 4 4
[18] 4 4 4 5 5 5 5 5
还能这样:
> x <- c(1,2,3,4,5)
> rep(x, each=5, time=2) # 不仅每个复制五次,害复制两遍
[1] 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 4 4
[18] 4 4 4 5 5 5 5 5 1 1 1 1 1 2 2 2 2
[35] 2 3 3 3 3 3 4 4 4 4 4 5 5 5 5 5
小补充:我们咋查看数据类型呢?我们可以通过class函数或mode函数查看向量的数据类型:
> class(x)
[1] "character"
> mode(x)
[1] "character"
讲了这么多向量的内容,那什么是标量呢?标量太好理解了,其实就是单个的数据呗,比如 a <- 0
或 a <- F
或 a <- 'str'
。
向量和基础语言不一样,起点是从1开始的:
> x <- 1:10
> x
[1] 1 2 3 4 5 6 7 8 9 10
> x[1] # 查找第一个
[1] 1
> x[0] # 没有第零个
integer(0)
> x[c(2, 5, 9)] # 多找几个
[1] 2 5 9
> x[5:7]
[1] 5 6 7
从上面我们也能看出来,正数就是索引,那负数是什么呢?其实索引的时候使用负号,我一般不称ta为负号,而是减号。因为这是代表删除元素的作用:
> x <- 1:10
> x
[1] 1 2 3 4 5 6 7 8 9 10
> x[-3] # 去除第三个元素
[1] 1 2 4 5 6 7 8 9 10
> x[c(-1,-3)] # 也可以删多个
[1] 2 4 5 6 7 8 9 10
> x[-1:-3]
[1] 4 5 6 7 8 9 10
所以我们也能看出来,正负数不能同时用的:
> x[c(-1,5)]
Error in x[c(-1, 5)] : only 0's may be mixed with negative subscripts
或者还能用逻辑值这样玩:
> x[c(T,T,T,F,F,F,T,T,T,F)] # 对应值为真就输出
[1] 1 2 3 7 8 9
> x[c(T, F)] # 自动拓展成TFTFTFTFTF
[1] 1 3 5 7 9
> x[c(T, T, F)] # 不是倍数也一样拓展TTFTTFTTFT
[1] 1 2 4 5 7 8 10
接下来,讲一个新的东西,可以用于判断一个元素是否在向量中,学过python的可能知道有in这个东西,R也差不多哦:
> x <- c('a', 'b', 'c', 'd', 'e')
> x
[1] "a" "b" "c" "d" "e"
> 'a' %in% x # 判断a在不在
[1] TRUE
> c('a', 'b') %in% x # 多判断几个,返回多个结果
[1] TRUE TRUE
################
# 我们再玩点花的 #
################
> x[x %in% c('b', 'c', 'f')] # 知道我咋完成的么
[1] "b" "c"
我们看看上面这个咋完成的?我们很简单就能看出来是输出x存在于后面数组中的元素,其实我们要看懂这个不难,把代码拆解开来看:
> x %in% c('b', 'c', 'f') # 分别判断x中的所有元素是否在后面的向量中
[1] FALSE TRUE TRUE FALSE FALSE
> x[c(F,T,T,F,F)] # 将判断结果用逻辑值的方法输出
[1] "b" "c"
接下来我们讲讲给向量中的元素取名字,其实取名字也就是做一个索引的字典而已,那我们怎么取名字呢?
> x <- 1:5
> x
[1] 1 2 3 4 5
> names(x) <- c('a', 'b', 'c', 'd', 'e') # 取名字
> x
a b c d e
1 2 3 4 5
取完名字我们就可以这样玩了:
> x['c']
c
3
还有,我们怎么在已有的向量后面追加元素呢?这个时候其实可以用到我们之前的知识,就是构造向量的知识:
> x <- 1:5
> x
[1] 1 2 3 4 5
> c(x, 6:9) # 利用创造向量的函数合并了向量
[1] 1 2 3 4 5 6 7 8 9
除了在后面追加还有插入元素(往后插):
> x <- 1:5
> x
[1] 1 2 3 4 5
> append(x, 2.5, 2) # append(向量,元素,第几个位置后面)
[1] 1.0 2.0 2.5 3.0 4.0 5.0
讲了追加,插入,还有删除,删除我一开始讲了,我就不讲了。
加一个which函数,用于查找索引值用的:
> x <- 9:1
> x
[1] 9 8 7 6 5 4 3 2 1
> which.max(x) # 查找最大值位置
[1] 1
> which.min(x) # 查找最小值位置
[1] 9
> which(x==2) # 查找为2的值的位置
[1] 8
> which(x>7) # 查找大于7的值的位置
[1] 1 2
其实从上面很容易发现,which是根据逻辑值的数组来确定的,也就是说我们也可以这样得到位置对应的值:
> x[which(x>7)]
[1] 9 8
说到向量的运算,是不是想到了数学里面向量的运算?对的!这也就是我们使用向量的根本原因之一,我们的计算就是以向量的方式完成的。
我们来拿加法举例,其他语言是不是数据要所有数据相加,要循环遍历然后相加?但是R可以直接使用向量的操作,其他语言的相信你会的~~(我懒得写其他语言的代码了)~~:
> x <- c(1, 2, 3, 4, 5)
> y <- c(6, 7, 8, 9, 0)
> x * 2 + y
[1] 8 11 14 17 10
所以我们可以罗列出向量的四则运算:
> x
[1] 1 2 3 4 5
> y
[1] 6 7 8 9 10
> x + y # 加
[1] 7 9 11 13 15
> x * y # 乘
[1] 6 14 24 36 50
> y - x # 减
[1] 5 5 5 5 5
> y / x # 除
[1] 6.000000 3.500000 2.666667
[4] 2.250000 2.000000
> x ** y # 幂
[1] 1 128 6561 262144
[5] 9765625
> y %% x # 取余
[1] 0 1 2 1 0
> y %/% x # 整除
[1] 6 3 2 2 2
这个地方有一个小细节,这里和我们之前的逻辑值拓展一样,如果x只有两个数,y有8个数,也是可以拓展相加的,但是四则运算的要求就一定是倍数,不能是别的了:
> x
[1] 1 2
> y
[1] 1 2 3 4 5 6 7 8
> x + y
[1] 2 4 4 6 6 8 8 10
> x * y
[1] 1 4 3 8 5 12 7 16
> y - x
[1] 0 0 2 2 4 4 6 6
> y / x
[1] 1 1 3 2 5 3 7 4
> y ** x
[1] 1 4 3 16 5 36 7 64
> y %% x
[1] 0 0 0 0 0 0 0 0
> y %/% x
[1] 1 1 3 2 5 3 7 4
> x <- 1:3
> y / x # 修改后不是倍数(有警告,而且不能兼容所有版本)
[1] 1.0 1.0 1.0 4.0 2.5 2.0 7.0 4.0
Warning message:
In y/x : longer object length is not a multiple of shorter object length
向量判断相等也是使用==,而非=负号,因为=符号也有赋值的作用,结果当然还是一个逻辑值数组:
> x <- 1:5
> y <- 6:10
> x
[1] 1 2 3 4 5
> y
[1] 6 7 8 9 10
> x == y
[1] FALSE FALSE FALSE FALSE FALSE
向量中还有一些方便的运算,我们来看看:
> x <- 1:18
> x
[1] 1 2 3 4 5 6 7 8 9 10 11
[12] 12 13 14 15 16 17 18
> x[x>6 & x<12] # 选取满足条件的项
[1] 7 8 9 10 11
> x>6 & x<12 # 判断满足条件的项
[1] FALSE FALSE FALSE FALSE FALSE
[6] FALSE TRUE TRUE TRUE TRUE
[11] TRUE FALSE FALSE FALSE FALSE
[16] FALSE FALSE FALSE
> y <- 1:3
> rep(y, 3:1) # 按照另一个向量中的每个数字复制n遍
[1] 1 1 1 2 2 3
我们再来看一些计算函数吧:
> x <- -5:5
> abs(x) # 绝对值
[1] 5 4 3 2 1 0 1 2 3 4 5
> x = abs(x)
> sqrt(x) # 求平方根
[1] 2.236068 2.000000 1.732051
[4] 1.414214 1.000000 0.000000
[7] 1.000000 1.414214 1.732051
[10] 2.000000 2.236068
> log(x) # 自然对数(当然可以换参数)
[1] 1.6094379 1.3862944 1.0986123
[4] 0.6931472 0.0000000 -Inf
[7] 0.0000000 0.6931472 1.0986123
[10] 1.3862944 1.6094379
> exp(x) # 自然对数的幂
[1] 148.413159 54.598150 20.085537
[4] 7.389056 2.718282 1.000000
[7] 2.718282 7.389056 20.085537
[10] 54.598150 148.413159
> x <- c(-2.4, -2.6, 2.4, 2.6)
> x
[1] -2.4 -2.6 2.4 2.6
> ceiling(x) # 向上取整
[1] -2 -2 3 3
> floor(x) # 想下取整
[1] -3 -3 2 2
> trunc(x) # 返回整数部分
[1] -2 -2 2 2
> round(x, 0) # 四舍五入,保留小数点后n位
[1] -2 -3 2 3
> signif(x, 1) # 四舍五入,保留有效数字
[1] -2 -3 2 3
> sin(x) # 正弦
[1] -0.6754632 -0.5155014 0.6754632
[4] 0.5155014
> cos(x) # 余弦
[1] -0.7373937 -0.8568888 -0.7373937
[4] -0.8568888
> sum(x) # 求和
[1] 0
> max(x) # 最大值
[1] 2.6
> min(x) # 最小值
[1] -2.6
> range(x) # 最大和最小值
[1] -2.6 2.6
> mean(x) # 平均值
[1] 0
> var(x) # 方差
[1] 8.346667
> sd(x) # 标准差
[1] 2.88906
> prod(x) # 连乘的积(全部相乘)
[1] 38.9376
> median(x) # 中位数
[1] 0
> quantile(x) # 分位数
0% 25% 50% 75% 100%
-2.60 -2.45 0.00 2.45 2.60
> quantile(x, c(0.4, 0.5, 0.8)) # 自定义计算分位数
40% 50% 80%
-1.44 0.00 2.48
向量是一维的,而矩阵是二维的,自然就有行和列,我们也把矩阵称作是有维数的向量。
例如我们有一些数据集就是矩阵:iris3
鸢尾花数据集,state.x77
美国50个州的8个指标。然后利用heatmap函数输入矩阵就可以得到热图,我们可以试试:
> heatmap(state.x77)
上面简单介绍了一些矩阵,接下来我们来看一下怎么创建一个矩阵。
我们说到矩阵就是一个有纬度的向量,所以向量和矩阵之间当然是可以相互转换的,比如一个一维的向量,裁成n等份,不就变成一个矩阵了吗?我们一起来看一下:
> x <- 1:20
> x
[1] 1 2 3 4 5 6 7 8 9 10 11
[12] 12 13 14 15 16 17 18 19 20
> mx <- matrix(x, 4, 5) # 将x拆分成四行五列
> mx
[,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
> mx <- matrix(x, 4) # 只给行或列参数会自动补全为4*5
> mx
[,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
> mx <- matrix(x, , 5)
> mx
[,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
但是这个是不是和想象中的有点不一样呢?对的,我们的数据是按列分布的(R语言中的默认情况就是按列分布),但我们很多时候需要的是按行分布,所以matrix还有第四个参数就是按行分布。
> mx <- matrix(1:20, 4, 5, T) # 第四个参数为TRUE表示按行分布
> mx
[,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
既然我们可以给向量中的每个数据命名,我们当然也可以给矩阵中的每行每列命名。我们来看一下命名方法:
> rname <- c('R1', 'R2', 'R3', 'R4')
> cname <- c('C1', 'C2', 'C3', 'C4', 'C5')
> rname
[1] "R1" "R2" "R3" "R4"
> cname
[1] "C1" "C2" "C3" "C4" "C5"
> dimnames(mx) <- list(rname, cname) # 给每行每列命名
> mx
C1 C2 C3 C4 C5
R1 1 2 3 4 5
R2 6 7 8 9 10
R3 11 12 13 14 15
R4 16 17 18 19 20
我们一样是拆分开来看:
> mx <- matrix(1:20, 4, 5)
> mx
[,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(mx) # 我们先来看一下dimname(mx)是啥,发现啥也没有
NULL
> class(dimnames(mx)) # 这个时候他也没有属性(但其实是纬度指标)
[1] "NULL"
> list(rname, cname) # 由行列名构成的指标
[[1]]
[1] "R1" "R2" "R3" "R4"
[[2]]
[1] "C1" "C2" "C3" "C4" "C5"
> dimnames(mx) <- list(rname, cname) # 给纬度向量命名
> dimnames(mx) # 现在纬度指标为列表了,并且为行、列两项
[[1]]
[1] "R1" "R2" "R3" "R4"
[[2]]
[1] "C1" "C2" "C3" "C4" "C5"
> mx
C1 C2 C3 C4 C5
R1 1 5 9 13 17
R2 2 6 10 14 18
R3 3 7 11 15 19
R4 4 8 12 16 20
这里的数组和我们平常说的数组不一样,一般是指多纬度的数组,比如二维三维,我们可以先构建一个二维数组(也就是矩阵)来看一下:
> x <- 1:20
> dim(x) <- c(4, 5) # 将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
可能有人说,这和matrix有什么不一样吗??这当然不一样,第一是用法不一样,第二是这个可以创造更高维度的数组。
什么叫用法不一样?是因为dim是直接对一个向量进行操作,改变ta的结构,而matrix是创造一个矩阵:
> 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
> y <- 1:20
> dim(y) <- c(4, 5) # 将y从一个一维向量变成矩阵
> y
[,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
什么叫更高维度的数组?是因为ta除了可以在一维向量和矩阵之间任意转换,更高维度也可以:
> y
[,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
> dim(y) <- c(2, 2, 5) # 将y从一个矩阵变成一个三维数组
> y
, , 1
[,1] [,2]
[1,] 1 3
[2,] 2 4
, , 2
[,1] [,2]
[1,] 5 7
[2,] 6 8
, , 3
[,1] [,2]
[1,] 9 11
[2,] 10 12
, , 4
[,1] [,2]
[1,] 13 15
[2,] 14 16
, , 5
[,1] [,2]
[1,] 17 19
[2,] 18 20
说到matrix可以创建矩阵,dim可以修改数组维度,那必然还有创造多维数组 的函数,那就是array函数:
> x <- array(1:20, c(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 <- array(1:9, c(3, 3, 3)) # 创建三维数组
> y
, , 1
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
, , 2
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
, , 3
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
> y <- array(1:9, c(3, 3, 3), dimnames = list(c('A1', 'A2', 'A3'), c('B1', 'B2', 'B3'), c('C1', 'C2', 'C3'))) # 还能给三个维度取名
> Y
Error: object 'Y' not found
> y
, , C1
B1 B2 B3
A1 1 4 7
A2 2 5 8
A3 3 6 9
, , C2
B1 B2 B3
A1 1 4 7
A2 2 5 8
A3 3 6 9
, , C3
B1 B2 B3
A1 1 4 7
A2 2 5 8
A3 3 6 9
索引也和向量中索引的方法很像,无非就是选取行列,删除行列,省略参数这样子的。
我们还是先来点基础的,选取行列:
> x <- matrix(1:20, 4, 5, T)
> x
[,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
> x[c(2, 3), c(3, 4)] # 选取2,3行,和3,4列
[,1] [,2]
[1,] 8 9
[2,] 13 14
或者是省略参数进行行列的索引:
> x[2,]
[1] 6 7 8 9 10
> x[,2]
[1] 2 7 12 17
还有我刚刚说的删除行列,然后还有一点就是,不同的参数是可以用到索引和删除的:
> x[-2, -2]
[,1] [,2] [,3] [,4]
[1,] 1 3 4 5
[2,] 11 13 14 15
[3,] 16 18 19 20
> x[c(-1, -4), 3] # 删除第一行,第四行后,输出第三行的向量
[1] 8 13
我们假设我们给矩阵的行列取了名字,那咋弄?其实也是一样的,只是可以用名字找到ta而已:
> x
[,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
> dimnames(x) <- list(rname, cname)
> x
C1 C2 C3 C4 C5
R1 1 2 3 4 5
R2 6 7 8 9 10
R3 11 12 13 14 15
R4 16 17 18 19 20
> x['R3', ]
C1 C2 C3 C4 C5
11 12 13 14 15
> x[, 'C4']
R1 R2 R3 R4
4 9 14 19
> x['R3', 'C4']
[1] 14
矩阵的运算,我想学过线性代数的同学应该都是会的,在这里简单的讲一下,矩阵的运算其实还是和前面向量的运算基本操作是一样的,什么叫一样的呢?就是指对应位置上进行操作,除了矩阵有一个特殊的乘法的性质:
> x <- matrix(1:20, 4, 5)
> y <- matrix(1:20, 5, 4)
> 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] [,2] [,3] [,4]
[1,] 1 6 11 16
[2,] 2 7 12 17
[3,] 3 8 13 18
[4,] 4 9 14 19
[5,] 5 10 15 20
> x + 1 # 加法
[,1] [,2] [,3] [,4] [,5]
[1,] 2 6 10 14 18
[2,] 3 7 11 15 19
[3,] 4 8 12 16 20
[4,] 5 9 13 17 21
> x * 2 # 乘法
[,1] [,2] [,3] [,4] [,5]
[1,] 2 10 18 26 34
[2,] 4 12 20 28 36
[3,] 6 14 22 30 38
[4,] 8 16 24 32 40
> x / 2 # 除法
[,1] [,2] [,3] [,4] [,5]
[1,] 0.5 2.5 4.5 6.5 8.5
[2,] 1.0 3.0 5.0 7.0 9.0
[3,] 1.5 3.5 5.5 7.5 9.5
[4,] 2.0 4.0 6.0 8.0 10.0
> x ** 2 # 幂运算
[,1] [,2] [,3] [,4] [,5]
[1,] 1 25 81 169 289
[2,] 4 36 100 196 324
[3,] 9 49 121 225 361
[4,] 16 64 144 256 400
> x + y # 不同样子的矩阵不能加
Error in x + y : non-conformable arrays
> x * y # 不同样子的矩阵不能内积
Error in x * y : non-conformable arrays
> x %*% y # 4*5和5*4的矩阵可以外积
[,1] [,2] [,3] [,4]
[1,] 175 400 625 850
[2,] 190 440 690 940
[3,] 205 480 755 1030
[4,] 220 520 820 1120
一些用来简便计算的函数,实在是挺简单的,所以就直接列出来不细讲:
> 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
> sum(x) # 求和
[1] 210
> colSums(x) # 列和
[1] 10 26 42 58 74
> rowSums(x) # 行和
[1] 45 50 55 60
> colMeans(x) # 列平均值
[1] 2.5 6.5 10.5 14.5 18.5
> rowMeans(x) # 行平均值
[1] 9 10 11 12
> diag(x) # 返回对角线上的值
[1] 1 6 11 16
> t(x) # 矩阵转置
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 8
[3,] 9 10 11 12
[4,] 13 14 15 16
[5,] 17 18 19 20
R语言中的列表是一种很复杂但也很重要的数据结构,这里的列表不像其他语言中的列表一样,单纯表示为一个数组。
R的列表是一些对象的集合,里面可以有向量、矩阵、数据框,或者另一个列表。所以可以知道,列表是R中最大的容器,类似于向量的结构,是一个一维数据的集合。和向量不同的地方就是可以存储不同的数据结构,包括列表本身。
我们的数据集中,state.center(美国各个州的经纬度) 就是一个列表,我们看一下:
> state.center
$x
[1] -86.7509 -127.2500 -111.6250 -92.2992
[5] -119.7730 -105.5130 -72.3573 -74.9841
[9] -81.6850 -83.3736 -126.2500 -113.9300
[13] -89.3776 -86.0808 -93.3714 -98.1156
[17] -84.7674 -92.2724 -68.9801 -76.6459
[21] -71.5800 -84.6870 -94.6043 -89.8065
[25] -92.5137 -109.3200 -99.5898 -116.8510
[29] -71.3924 -74.2336 -105.9420 -75.1449
[33] -78.4686 -100.0990 -82.5963 -97.1239
[37] -120.0680 -77.4500 -71.1244 -80.5056
[41] -99.7238 -86.4560 -98.7857 -111.3300
[45] -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
[7] 41.5928 38.6777 27.8744 32.3329 31.7500 43.5648
[13] 40.0495 40.0495 41.9358 38.4204 37.3915 30.6181
[19] 45.6226 39.2778 42.3645 43.1361 46.3943 32.6758
[25] 38.3347 46.8230 41.3356 39.1063 43.3934 39.9637
[31] 34.4764 43.1361 35.4195 47.2517 40.2210 35.5053
[37] 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
[49] 44.5937 43.0504
和往常一样,学习这个数据结构要先会创建ta:
> ls = list(1, "str", T, matrix(1:20, 4, 5)) # 创建列表
> ls
[[1]]
[1] 1
[[2]]
[1] "str"
[[3]]
[1] TRUE
[[4]]
[,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
其实列表这样就已经创建好了,很简单。当然,像其他数据结构一样,我们可以为每一项取名儿:
> ls = list(first=1, second="str", third=T, forth=matrix(1:20, 4, 5)) # 直接在参数前面给ta取名
> ls
$first
[1] 1
$second
[1] "str"
$third
[1] TRUE
$forth
[,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
列表的索引和向量的索引又双叒叕是非常像的,我把相同的地方在这里简单的敲一遍吧:
> ls
$first
[1] 1
$second
[1] "str"
$third
[1] TRUE
$forth
[,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
> ls[1] # 索引单个值
$first
[1] 1
> ls[c(2, 4)] # 访问多个元素
$second
[1] "str"
$forth
[,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
> ls[c('second', 'forth')] # 用名字访问
$second
[1] "str"
$forth
[,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
> ls[-4] # 负索引删除
$first
[1] 1
$second
[1] "str"
$third
[1] TRUE
既然说了相同,那必有不同的地方,就是使用$符号进行列表元素的索引,方法高效,也很方便:
> ls$third # 直接索引名字为third的元素
[1] TRUE
关于索引的方法也是有讲究的,我们先看一下下面这个案例:
> ls[4]
$forth
[,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
> ls[[4]]
[,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
你有发现有什么不同吗?从输出上来看是没有什么不同,只是ls[[4]]
中少了一个$forth
而已。但是这个地方是从根本上进行了改变。
有$forth
说明了什么?说明ls[4]
其实是一个列表,我们可以发现ta和前面的列表构造很像,不过只有一个数罢了。所以我们可以看出来,ls[4]
只是把第四项取出来成为了一个新的列表了(我们也能发现R语言所有的数据结构,在索引的时候都可以选择多个数据,因为这样方便构造一个新的一样的数据结构)。
然后当我们输入ls[[4]]
的时候,可以发现输出的就是一个矩阵,也就是我们把这个元素原本的属性输出来了!
我们来验证一下:
> class(ls[4])
[1] "list"
> class(ls[[4]])
[1] "matrix" "array"
可见我们的猜测非常正确,哎嘿
讲这个有啥用呢?wok,用处可大了,我们赋值的时候总不能把一个matrix赋值给一个list吧!所以我们赋值的时候就要注意了:
> ls
$forth
[,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
> ls[1] <- matrix(1:16, 4, 4) # 给ls[1]赋值
Warning message:
In ls[1] <- matrix(1:16, 4, 4) :
number of items to replace is not a multiple of replacement length
> ls
$forth
[1] 1
> ls[[1]] <- matrix(1:16, 4, 4) # 给ls[[1]]赋值
> ls
$forth
[,1] [,2] [,3] [,4]
[1,] 1 5 9 13
[2,] 2 6 10 14
[3,] 3 7 11 15
[4,] 4 8 12 16
> class(ls$forth) # 看看$索引的元素性质
[1] "matrix" "array"
> ls$forth <- matrix(1:20, 4, 5) # 也可以给$索引的元素赋值
> ls
$forth
[,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
我主要就讲两个列表操作吧,一个是追加,一个是删除。
首先是追加,追加和我们之前在向量中运用的技巧一样,可以用向量追加东西:
> ls
$first
[1] 1
$second
[1] "str"
$third
[1] TRUE
$forth
[,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
> ls <- c(ls, list(matrix(1:20, 4, 5))) # 追加一个4*5的矩阵
> ls
$first
[1] 1
$second
[1] "str"
$third
[1] TRUE
$forth
[,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
[[5]]
[,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
还有一个就是删除,删除除了负索引,还可以使用别的方法,因为有的时候我们也想使用名称索引:
> ls
$first
[1] 1
$second
[1] "str"
$third
[1] TRUE
$forth
[,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
> ls$second <- NULL # 删除名称为second的元素
> ls
$first
[1] 1
$third
[1] TRUE
$forth
[,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
作用:数据框用于模拟数据集,和SPSS或SAS中的数据集的概念是一致的。
简单der介绍:数据集通常是数据构成的矩形数组。统计学中将行称为观测,列称为变量,数据库中称为记录和字段,机器学习上称为示例与属性(根据不同的作用进行区分)。
(ps:数据框是一个矩形的结构,但不是由矩阵进行实现的,本质上是一个列表)。
数据框是由:列表+等长的向量,组成的。然后数据框的列表中的元素是必须有名字的!
所以在这里是很好理解的,我们的数据框就是被分成了这样的几个部分。
所以我们可以总结出几个数据框的特点:
然后我们的内置数据集中就有大量的数据框的结构:
> class(iris) # 鸢尾花数据集
[1] "data.frame"
> class(mtcars) # 32辆车在11个指标上的数据
[1] "data.frame"
讲完概念,终于也到了构建数据框的时候了,构建数据框也不难,也是依靠一个函数:data.frame()
来构建的。我们在data.frame()
中放入一至多个,向量和矩阵,只要行数一样就可以合并了。
我们先来个简单的例子:
> data.frame(matrix(1:20, 4, 5))
X1 X2 X3 X4 X5
1 1 5 9 13 17
2 2 6 10 14 18
3 3 7 11 15 19
4 4 8 12 16 20
从这个例子中我们发现了什么!发现了数据框的列是一定要有名字的!因为我们没有给他赋予名字,所以R自动为我们的矩阵创造了一个列名。
我们在来做一个合并的:
> df <- data.frame(matrix(1:20, 4, 5), c(21:24)) # 合并一个矩阵和一个向量
> df
X1 X2 X3 X4 X5 c.21.24.
1 1 5 9 13 17 21
2 2 6 10 14 18 22
3 3 7 11 15 19 23
4 4 8 12 16 20 24
以上都是我们没有取名的例子,所以列名都是系统自动给的。下面我们用系统给的数据集来做一个案例。
我们知道state.name, state.abb, state.region, state.x77
是美国50个州的各种数据,这四个分别为向量、向量、向量、矩阵,而且行名都对应为相应的州的名字:
> state.name # 州的名字
[1] "Alabama" "Alaska" "Arizona"
[4] "Arkansas" "California" "Colorado"
[7] "Connecticut" "Delaware" "Florida"
[10] "Georgia" "Hawaii" "Idaho"
[13] "Illinois" "Indiana" "Iowa"
[16] "Kansas" "Kentucky" "Louisiana"
[19] "Maine" "Maryland" "Massachusetts"
[22] "Michigan" "Minnesota" "Mississippi"
[25] "Missouri" "Montana" "Nebraska"
[28] "Nevada" "New Hampshire" "New Jersey"
[31] "New Mexico" "New York" "North Carolina"
[34] "North Dakota" "Ohio" "Oklahoma"
[37] "Oregon" "Pennsylvania" "Rhode Island"
[40] "South Carolina" "South Dakota" "Tennessee"
[43] "Texas" "Utah" "Vermont"
[46] "Virginia" "Washington" "West Virginia"
[49] "Wisconsin" "Wyoming"
> state.abb # 名字的缩写
[1] "AL" "AK" "AZ" "AR" "CA" "CO" "CT" "DE" "FL"
[10] "GA" "HI" "ID" "IL" "IN" "IA" "KS" "KY" "LA"
[19] "ME" "MD" "MA" "MI" "MN" "MS" "MO" "MT" "NE"
[28] "NV" "NH" "NJ" "NM" "NY" "NC" "ND" "OH" "OK"
[37] "OR" "PA" "RI" "SC" "SD" "TN" "TX" "UT" "VT"
[46] "VA" "WA" "WV" "WI" "WY"
> state.region # 所在的地区
[1] South West West
[4] South West West
[7] Northeast South South
[10] South West West
[13] North Central North Central North Central
[16] North Central South South
[19] Northeast South Northeast
[22] North Central North Central South
[25] North Central West North Central
[28] West Northeast Northeast
[31] West Northeast South
[34] North Central North Central South
[37] West Northeast Northeast
[40] South North Central South
[43] South West Northeast
[46] South West South
[49] North Central West
Levels: Northeast South North Central West
> state.x77 # 50个州的详细数据
Population Income Illiteracy
Alabama 3615 3624 2.1
Alaska 365 6315 1.5
Arizona 2212 4530 1.8
Arkansas 2110 3378 1.9
California 21198 5114 1.1
Colorado 2541 4884 0.7
Connecticut 3100 5348 1.1
Delaware 579 4809 0.9
Florida 8277 4815 1.3
Georgia 4931 4091 2.0
Hawaii 868 4963 1.9
Idaho 813 4119 0.6
Illinois 11197 5107 0.9
Indiana 5313 4458 0.7
Iowa 2861 4628 0.5
Kansas 2280 4669 0.6
Kentucky 3387 3712 1.6
Louisiana 3806 3545 2.8
Maine 1058 3694 0.7
Maryland 4122 5299 0.9
Massachusetts 5814 4755 1.1
Michigan 9111 4751 0.9
Minnesota 3921 4675 0.6
Mississippi 2341 3098 2.4
Missouri 4767 4254 0.8
Montana 746 4347 0.6
Nebraska 1544 4508 0.6
Nevada 590 5149 0.5
New Hampshire 812 4281 0.7
New Jersey 7333 5237 1.1
New Mexico 1144 3601 2.2
New York 18076 4903 1.4
North Carolina 5441 3875 1.8
North Dakota 637 5087 0.8
Ohio 10735 4561 0.8
Oklahoma 2715 3983 1.1
Oregon 2284 4660 0.6
Pennsylvania 11860 4449 1.0
Rhode Island 931 4558 1.3
South Carolina 2816 3635 2.3
South Dakota 681 4167 0.5
Tennessee 4173 3821 1.7
Texas 12237 4188 2.2
Utah 1203 4022 0.6
Vermont 472 3907 0.6
Virginia 4981 4701 1.4
Washington 3559 4864 0.6
West Virginia 1799 3617 1.4
Wisconsin 4589 4468 0.7
Wyoming 376 4566 0.6
Life Exp Murder HS Grad Frost Area
Alabama 69.05 15.1 41.3 20 50708
Alaska 69.31 11.3 66.7 152 566432
Arizona 70.55 7.8 58.1 15 113417
Arkansas 70.66 10.1 39.9 65 51945
California 71.71 10.3 62.6 20 156361
Colorado 72.06 6.8 63.9 166 103766
Connecticut 72.48 3.1 56.0 139 4862
Delaware 70.06 6.2 54.6 103 1982
Florida 70.66 10.7 52.6 11 54090
Georgia 68.54 13.9 40.6 60 58073
Hawaii 73.60 6.2 61.9 0 6425
Idaho 71.87 5.3 59.5 126 82677
Illinois 70.14 10.3 52.6 127 55748
Indiana 70.88 7.1 52.9 122 36097
Iowa 72.56 2.3 59.0 140 55941
Kansas 72.58 4.5 59.9 114 81787
Kentucky 70.10 10.6 38.5 95 39650
Louisiana 68.76 13.2 42.2 12 44930
Maine 70.39 2.7 54.7 161 30920
Maryland 70.22 8.5 52.3 101 9891
Massachusetts 71.83 3.3 58.5 103 7826
Michigan 70.63 11.1 52.8 125 56817
Minnesota 72.96 2.3 57.6 160 79289
Mississippi 68.09 12.5 41.0 50 47296
Missouri 70.69 9.3 48.8 108 68995
Montana 70.56 5.0 59.2 155 145587
Nebraska 72.60 2.9 59.3 139 76483
Nevada 69.03 11.5 65.2 188 109889
New Hampshire 71.23 3.3 57.6 174 9027
New Jersey 70.93 5.2 52.5 115 7521
New Mexico 70.32 9.7 55.2 120 121412
New York 70.55 10.9 52.7 82 47831
North Carolina 69.21 11.1 38.5 80 48798
North Dakota 72.78 1.4 50.3 186 69273
Ohio 70.82 7.4 53.2 124 40975
Oklahoma 71.42 6.4 51.6 82 68782
Oregon 72.13 4.2 60.0 44 96184
Pennsylvania 70.43 6.1 50.2 126 44966
Rhode Island 71.90 2.4 46.4 127 1049
South Carolina 67.96 11.6 37.8 65 30225
South Dakota 72.08 1.7 53.3 172 75955
Tennessee 70.11 11.0 41.8 70 41328
Texas 70.90 12.2 47.4 35 262134
Utah 72.90 4.5 67.3 137 82096
Vermont 71.64 5.5 57.1 168 9267
Virginia 70.08 9.5 47.8 85 39780
Washington 71.72 4.3 63.5 32 66570
West Virginia 69.48 6.7 41.6 100 24070
Wisconsin 72.48 3.0 54.5 149 54464
Wyoming 70.29 6.9 62.9 173 97203
那我们这里的三个向量和一个矩阵就可以合并称为一个描述美国的很好的数据框,我们来试一试:
> df <- data.frame(state.name, state.abb, state.region, state.x77) # 将这四个属性进行合并
而且打开一看,属实觉得界面比Excel界面好看,学R学出了幻觉。
构建一个数据框还是一个小事,最重要的还是我们怎么去使用我们的数据框,第一个要做的自然就是索引。
首先讲一个又双叒叕和其他数据结构,可以直接索引列的值:
> df[c(2, 4)] # 查询2,4列
state.abb Population
Alabama AL 3615
Alaska AK 365
Arizona AZ 2212
Arkansas AR 2110
California CA 21198
Colorado CO 2541
Connecticut CT 3100
Delaware DE 579
Florida FL 8277
Georgia GA 4931
Hawaii HI 868
Idaho ID 813
Illinois IL 11197
Indiana IN 5313
Iowa IA 2861
Kansas KS 2280
Kentucky KY 3387
Louisiana LA 3806
Maine ME 1058
Maryland MD 4122
Massachusetts MA 5814
Michigan MI 9111
Minnesota MN 3921
Mississippi MS 2341
Missouri MO 4767
Montana MT 746
Nebraska NE 1544
Nevada NV 590
New Hampshire NH 812
New Jersey NJ 7333
New Mexico NM 1144
New York NY 18076
North Carolina NC 5441
North Dakota ND 637
Ohio OH 10735
Oklahoma OK 2715
Oregon OR 2284
Pennsylvania PA 11860
Rhode Island RI 931
South Carolina SC 2816
South Dakota SD 681
Tennessee TN 4173
Texas TX 12237
Utah UT 1203
Vermont VT 472
Virginia VA 4981
Washington WA 3559
West Virginia WV 1799
Wisconsin WI 4589
Wyoming WY 376
> df[-c(3:9)] # 删除3:9列
state.name state.abb Frost Area
Alabama Alabama AL 20 50708
Alaska Alaska AK 152 566432
Arizona Arizona AZ 15 113417
Arkansas Arkansas AR 65 51945
California California CA 20 156361
Colorado Colorado CO 166 103766
Connecticut Connecticut CT 139 4862
Delaware Delaware DE 103 1982
Florida Florida FL 11 54090
Georgia Georgia GA 60 58073
Hawaii Hawaii HI 0 6425
Idaho Idaho ID 126 82677
Illinois Illinois IL 127 55748
Indiana Indiana IN 122 36097
Iowa Iowa IA 140 55941
Kansas Kansas KS 114 81787
Kentucky Kentucky KY 95 39650
Louisiana Louisiana LA 12 44930
Maine Maine ME 161 30920
Maryland Maryland MD 101 9891
Massachusetts Massachusetts MA 103 7826
Michigan Michigan MI 125 56817
Minnesota Minnesota MN 160 79289
Mississippi Mississippi MS 50 47296
Missouri Missouri MO 108 68995
Montana Montana MT 155 145587
Nebraska Nebraska NE 139 76483
Nevada Nevada NV 188 109889
New Hampshire New Hampshire NH 174 9027
New Jersey New Jersey NJ 115 7521
New Mexico New Mexico NM 120 121412
New York New York NY 82 47831
North Carolina North Carolina NC 80 48798
North Dakota North Dakota ND 186 69273
Ohio Ohio OH 124 40975
Oklahoma Oklahoma OK 82 68782
Oregon Oregon OR 44 96184
Pennsylvania Pennsylvania PA 126 44966
Rhode Island Rhode Island RI 127 1049
South Carolina South Carolina SC 65 30225
South Dakota South Dakota SD 172 75955
Tennessee Tennessee TN 70 41328
Texas Texas TX 35 262134
Utah Utah UT 137 82096
Vermont Vermont VT 168 9267
Virginia Virginia VA 85 39780
Washington Washington WA 32 66570
West Virginia West Virginia WV 100 24070
Wisconsin Wisconsin WI 149 54464
Wyoming Wyoming WY 173 97203
上面这个选择索引和删除索引返回的都是数据框对象,和我们之前学列表的时候是一样的,可以类比。那怎么把数据框变成原数据类型的实体呢?其实和以前也是一样的~
> df[[2]] # 用双中括号进行取值
[1] "AL" "AK" "AZ" "AR" "CA" "CO" "CT" "DE" "FL" "GA" "HI"
[12] "ID" "IL" "IN" "IA" "KS" "KY" "LA" "ME" "MD" "MA" "MI"
[23] "MN" "MS" "MO" "MT" "NE" "NV" "NH" "NJ" "NM" "NY" "NC"
[34] "ND" "OH" "OK" "OR" "PA" "RI" "SC" "SD" "TN" "TX" "UT"
[45] "VT" "VA" "WA" "WV" "WI" "WY"
> df$state.abb # 用$符号进行取值
[1] "AL" "AK" "AZ" "AR" "CA" "CO" "CT" "DE" "FL" "GA" "HI"
[12] "ID" "IL" "IN" "IA" "KS" "KY" "LA" "ME" "MD" "MA" "MI"
[23] "MN" "MS" "MO" "MT" "NE" "NV" "NH" "NJ" "NM" "NY" "NC"
[34] "ND" "OH" "OK" "OR" "PA" "RI" "SC" "SD" "TN" "TX" "UT"
[45] "VT" "VA" "WA" "WV" "WI" "WY"
我们现在已经知道怎么取列的值了,然后我们自然就会想怎么去取某个位置的值,或者怎么取某一行的值。这就要牵扯到两个参数的索引方法的应用了:
> df <- array(1:16, c(4, 4), dimnames = list(c('R1', 'R2', 'R3', 'R4'), c('C1', 'C2', 'C3', 'C4')))
> df <- data.frame(df)
> df
C1 C2 C3 C4
R1 1 5 9 13
R2 2 6 10 14
R3 3 7 11 15
R4 4 8 12 16
> df['R3', 'C4'] # 输出第三行第四列的值
[1] 15
所以我们很清楚的就能知道,两个参数就是先行后列,所以我们想输出某一行或某一列也就可以使用这样的方法:
> df['R3', ]
C1 C2 C3 C4
R3 3 7 11 15
> df[, 'C4']
[1] 13 14 15 16
然后R还给我们提供两种面向数据框比较方便的函数:attach函数和with函数。
attach函数:其实就是将数据框加载入系统,然后列名就相当于称为了变量,可以直接调用了(然后我们可以用detach函数关闭加载),我们来试试:
> attach(df)
> C1
[1] 1 2 3 4
> C2
[1] 5 6 7 8
> detach(df)
> C1
Error: object 'C1' not found
> C2
Error: object 'C2' not found
with函数:这个函数的作用就类似于$符号的作用,可以索引某一个数据框的某一列,还能进行一些操作,虽然大部分时间没有$符号好用:
> with(df, {C1}) # 输出df数据框的C1列
[1] 1 2 3 4
> with(df, {sum(C1)}) # 输出df数据框C1列的和
[1] 10
因子也是R中非常重要的一个数据结构,要了解因子是什么,我们要先了解一下变量有哪些种类:
在R中,名义型变量和有序型变量就被称为因子,这些变量都以等级分类,比如:优、良、差,被称为等级。由这些等级构成的向量就被称为因子。
因子最大的作用就是用来分类,计算频数和频率。
上面所说,因子可以用于分类,将变量以等级来区分。所以因子在应用上可以有:
我们以mtcars数据集做计算频数的举例:
> mtcars
mpg cyl disp hp drat wt
Mazda RX4 21.0 6 160.0 110 3.90 2.620
Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875
Datsun 710 22.8 4 108.0 93 3.85 2.320
Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215
Hornet Sportabout 18.7 8 360.0 175 3.15 3.440
Valiant 18.1 6 225.0 105 2.76 3.460
Duster 360 14.3 8 360.0 245 3.21 3.570
Merc 240D 24.4 4 146.7 62 3.69 3.190
Merc 230 22.8 4 140.8 95 3.92 3.150
Merc 280 19.2 6 167.6 123 3.92 3.440
Merc 280C 17.8 6 167.6 123 3.92 3.440
Merc 450SE 16.4 8 275.8 180 3.07 4.070
Merc 450SL 17.3 8 275.8 180 3.07 3.730
Merc 450SLC 15.2 8 275.8 180 3.07 3.780
Cadillac Fleetwood 10.4 8 472.0 205 2.93 5.250
Lincoln Continental 10.4 8 460.0 215 3.00 5.424
Chrysler Imperial 14.7 8 440.0 230 3.23 5.345
Fiat 128 32.4 4 78.7 66 4.08 2.200
Honda Civic 30.4 4 75.7 52 4.93 1.615
Toyota Corolla 33.9 4 71.1 65 4.22 1.835
Toyota Corona 21.5 4 120.1 97 3.70 2.465
Dodge Challenger 15.5 8 318.0 150 2.76 3.520
AMC Javelin 15.2 8 304.0 150 3.15 3.435
Camaro Z28 13.3 8 350.0 245 3.73 3.840
Pontiac Firebird 19.2 8 400.0 175 3.08 3.845
Fiat X1-9 27.3 4 79.0 66 4.08 1.935
Porsche 914-2 26.0 4 120.3 91 4.43 2.140
Lotus Europa 30.4 4 95.1 113 3.77 1.513
Ford Pantera L 15.8 8 351.0 264 4.22 3.170
Ferrari Dino 19.7 6 145.0 175 3.62 2.770
Maserati Bora 15.0 8 301.0 335 3.54 3.570
Volvo 142E 21.4 4 121.0 109 4.11 2.780
qsec vs am gear carb
Mazda RX4 16.46 0 1 4 4
Mazda RX4 Wag 17.02 0 1 4 4
Datsun 710 18.61 1 1 4 1
Hornet 4 Drive 19.44 1 0 3 1
Hornet Sportabout 17.02 0 0 3 2
Valiant 20.22 1 0 3 1
Duster 360 15.84 0 0 3 4
Merc 240D 20.00 1 0 4 2
Merc 230 22.90 1 0 4 2
Merc 280 18.30 1 0 4 4
Merc 280C 18.90 1 0 4 4
Merc 450SE 17.40 0 0 3 3
Merc 450SL 17.60 0 0 3 3
Merc 450SLC 18.00 0 0 3 3
Cadillac Fleetwood 17.98 0 0 3 4
Lincoln Continental 17.82 0 0 3 4
Chrysler Imperial 17.42 0 0 3 4
Fiat 128 19.47 1 1 4 1
Honda Civic 18.52 1 1 4 2
Toyota Corolla 19.90 1 1 4 1
Toyota Corona 20.01 1 0 3 1
Dodge Challenger 16.87 0 0 3 2
AMC Javelin 17.30 0 0 3 2
Camaro Z28 15.41 0 0 3 4
Pontiac Firebird 17.05 0 0 3 2
Fiat X1-9 18.90 1 1 4 1
Porsche 914-2 16.70 0 1 5 2
Lotus Europa 16.90 1 1 5 2
Ford Pantera L 14.50 0 1 5 4
Ferrari Dino 15.50 0 1 5 6
Maserati Bora 14.60 0 1 5 8
Volvo 142E 18.60 1 1 4 2
根据cyl汽车缸数,我们可以计算这些汽车的频数:
> table(mtcars$cyl) # table函数用于频数统计
4 6 8
11 7 14
备注:可以用来做因子的均可以这样做。
我们这里叫因子的定义,而不叫因子的构造,本质上是因为因子是基于向量发展而来的,向量可以转变为因子。
我们可以使用factor函数定义一个可以作为因子的向量,在这里我们举例:
> f <- factor(c('red', 'green', 'blue', 'green', 'blue'))
> f
[1] red green blue green blue
Levels: blue green red
> class(f)
[1] "factor"
显而易见,我们所有的‘等级’,在这里也就是三种颜色,被认为做等级,构造成了一个因子。
除了让系统自行构造因子的等级,我们还可以自己定义等级:
> f <- factor(c('a', 'b', 'c'), ordered = T, levels = c('a', 'b', 'c'))
> f
[1] a b c
Levels: a < b < c
第一个参数好理解,是我们的向量,levels参数好理解,是我们设定的等级。那我们还有一个参数ordered是什么呢?其实ordered是判断是否要根据输入的等级进行排序。我们可以看到输出的等级是有分大小的,所以ordered判定为TRUE是让我们输入的因子从小到大进行排序。
factor除了定义一个新的因子,还可以将一个向量定义为因子。还是用之前的例子,mtcars中的汽车缸数cyl就可以转化为因子。
> f <- factor(mtcars$cyl)
> f
[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
[26] 4 4 4 8 6 8 4
Levels: 4 6 8
因子还有什么特性呢?既然我们说因子可以用来分组,那我们尝试一下在画图上有没有什么不一样的。一般我们都知道一堆数据在画图的时候都会变成一堆点,那分了组是不是就是柱状图了呢?我们来试试:
> plot(mtcars$cyl)
> plot(factor(mtcars$cyl))
所以我们的想法是对的,其实从table的分组结果也能猜到这个效果。
除此之外,我们还会将连续区间划成段进行分组,比如考试分数满分为100分,每十分我们可以划一段,这里我们就可以用到cut函数了:
> plot(mtcars$cyl)
> plot(factor(mtcars$cyl))
> ls <- c(1, 65, 23, 40, 80, 99, 29, 100, 34)
> cut(ls, c(seq(0, 100, 10)))
[1] (0,10] (60,70] (20,30] (30,40] (70,80]
[6] (90,100] (20,30] (90,100] (30,40]
10 Levels: (0,10] (10,20] (20,30] (30,40] ... (90,100]
这样我们列表中的每个数都被这个等级取代使用了。
然后我们看完知识点后,也可以观察一下系统的数据集中,state.division和stata.region是因子类型的数据。
R中有很多内置的时间序列数据集,我们可以列举几个:
> sunspots # 太阳黑子数
Jan Feb Mar Apr May Jun Jul Aug Sep
1749 58.0 62.6 70.0 55.7 85.0 83.5 94.8 66.3 75.9
1750 73.3 75.9 89.2 88.3 90.0 100.0 85.4 103.0 91.2
1751 70.0 43.5 45.3 56.4 60.7 50.7 66.3 59.8 23.5
1752 35.0 50.0 71.0 59.3 59.7 39.6 78.4 29.3 27.1
1753 44.0 32.0 45.7 38.0 36.0 31.7 22.2 39.0 28.0
1754 0.0 3.0 1.7 13.7 20.7 26.7 18.8 12.3 8.2
1755 10.2 11.2 6.8 6.5 0.0 0.0 8.6 3.2 17.8
1756 12.5 7.1 5.4 9.4 12.5 12.9 3.6 6.4 11.8
1757 14.1 21.2 26.2 30.0 38.1 12.8 25.0 51.3 39.7
1758 37.6 52.0 49.0 72.3 46.4 45.0 44.0 38.7 62.5
1759 48.3 44.0 46.8 47.0 49.0 50.0 51.0 71.3 77.2
1760 67.3 59.5 74.7 58.3 72.0 48.3 66.0 75.6 61.3
1761 70.0 91.0 80.7 71.7 107.2 99.3 94.1 91.1 100.7
1762 43.8 72.8 45.7 60.2 39.9 77.1 33.8 67.7 68.5
1763 56.5 31.9 34.2 32.9 32.7 35.8 54.2 26.5 68.1
1764 59.7 59.7 40.2 34.4 44.3 30.0 30.0 30.0 28.2
1765 24.0 26.0 25.0 22.0 20.2 20.0 27.0 29.7 16.0
1766 12.0 11.0 36.6 6.0 26.8 3.0 3.3 4.0 4.3
1767 27.4 30.0 43.0 32.9 29.8 33.3 21.9 40.8 42.7
1768 53.5 66.1 46.3 42.7 77.7 77.4 52.6 66.8 74.8
1769 73.9 64.2 64.3 96.7 73.6 94.4 118.6 120.3 148.8
1770 104.0 142.5 80.1 51.0 70.1 83.3 109.8 126.3 104.4
1771 36.0 46.2 46.7 64.9 152.7 119.5 67.7 58.5 101.4
1772 100.9 90.8 31.1 92.2 38.0 57.0 77.3 56.2 50.5
1773 54.6 29.0 51.2 32.9 41.1 28.4 27.7 12.7 29.3
1774 46.8 65.4 55.7 43.8 51.3 28.5 17.5 6.6 7.9
1775 4.4 0.0 11.6 11.2 3.9 12.3 1.0 7.9 3.2
1776 21.7 11.6 6.3 21.8 11.2 19.0 1.0 24.2 16.0
1777 45.0 36.5 39.0 95.5 80.3 80.7 95.0 112.0 116.2
1778 177.3 109.3 134.0 145.0 238.9 171.6 153.0 140.0 171.7
1779 114.7 165.7 118.0 145.0 140.0 113.7 143.0 112.0 111.0
1780 70.0 98.0 98.0 95.0 107.2 88.0 86.0 86.0 93.7
1781 98.7 74.7 53.0 68.3 104.7 97.7 73.5 66.0 51.0
1782 54.0 37.5 37.0 41.0 54.3 38.0 37.0 44.0 34.0
1783 28.0 38.7 26.7 28.3 23.0 25.2 32.2 20.0 18.0
1784 13.0 8.0 11.0 10.0 6.0 9.0 6.0 10.0 10.0
1785 6.5 8.0 9.0 15.7 20.7 26.3 36.3 20.0 32.0
1786 37.2 47.6 47.7 85.4 92.3 59.0 83.0 89.7 111.5
1787 134.7 106.0 87.4 127.2 134.8 99.2 128.0 137.2 157.3
1788 138.0 129.2 143.3 108.5 113.0 154.2 141.5 136.0 141.0
1789 114.0 125.3 120.0 123.3 123.5 120.0 117.0 103.0 112.0
1790 103.0 127.5 96.3 94.0 93.0 91.0 69.3 87.0 77.3
1791 72.7 62.0 74.0 77.2 73.7 64.2 71.0 43.0 66.5
1792 58.0 64.0 63.0 75.7 62.0 61.0 45.8 60.0 59.0
1793 56.0 55.0 55.5 53.0 52.3 51.0 50.0 29.3 24.0
1794 45.0 44.0 38.0 28.4 55.7 41.5 41.0 40.0 11.1
1795 21.4 39.9 12.6 18.6 31.0 17.1 12.9 25.7 13.5
1796 22.0 23.8 15.7 31.7 21.0 6.7 26.9 1.5 18.4
1797 14.4 4.2 4.0 4.0 7.3 11.1 4.3 6.0 5.7
1798 2.0 4.0 12.4 1.1 0.0 0.0 0.0 3.0 2.4
1799 1.6 12.6 21.7 8.4 8.2 10.6 2.1 0.0 0.0
1800 6.9 9.3 13.9 0.0 5.0 23.7 21.0 19.5 11.5
1801 27.0 29.0 30.0 31.0 32.0 31.2 35.0 38.7 33.5
1802 47.8 47.0 40.8 42.0 44.0 46.0 48.0 50.0 51.8
1803 50.0 50.8 29.5 25.0 44.3 36.0 48.3 34.1 45.3
1804 45.3 48.3 48.0 50.6 33.4 34.8 29.8 43.1 53.0
1805 61.0 44.1 51.4 37.5 39.0 40.5 37.6 42.7 44.4
1806 39.0 29.6 32.7 27.7 26.4 25.6 30.0 26.3 24.0
1807 12.0 12.2 9.6 23.8 10.0 12.0 12.7 12.0 5.7
1808 0.0 4.5 0.0 12.3 13.5 13.5 6.7 8.0 11.7
1809 7.2 9.2 0.9 2.5 2.0 7.7 0.3 0.2 0.4
1810 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
1811 0.0 0.0 0.0 0.0 0.0 0.0 6.6 0.0 2.4
1812 11.3 1.9 0.7 0.0 1.0 1.3 0.5 15.6 5.2
1813 0.0 10.3 1.9 16.6 5.5 11.2 18.3 8.4 15.3
1814 22.2 12.0 5.7 23.8 5.8 14.9 18.5 2.3 8.1
1815 19.2 32.2 26.2 31.6 9.8 55.9 35.5 47.2 31.5
1816 26.3 68.8 73.7 58.8 44.3 43.6 38.8 23.2 47.8
1817 36.4 57.9 96.2 26.4 21.2 40.0 50.0 45.0 36.7
1818 34.9 22.4 25.4 34.5 53.1 36.4 28.0 31.5 26.1
1819 32.5 20.7 3.7 20.2 19.6 35.0 31.4 26.1 14.9
1820 19.2 26.6 4.5 19.4 29.3 10.8 20.6 25.9 5.2
1821 21.5 4.3 5.7 9.2 1.7 1.8 2.5 4.8 4.4
1822 0.0 0.9 16.1 13.5 1.5 5.6 7.9 2.1 0.0
1823 0.0 0.0 0.6 0.0 0.0 0.0 0.5 0.0 0.0
1824 21.6 10.8 0.0 19.4 2.8 0.0 0.0 1.4 20.5
1825 5.0 15.5 22.4 3.8 15.4 15.4 30.9 25.4 15.7
1826 17.7 18.2 36.7 24.0 32.4 37.1 52.5 39.6 18.9
1827 34.6 47.4 57.8 46.0 56.3 56.7 42.9 53.7 49.6
1828 52.8 64.4 65.0 61.1 89.1 98.0 54.3 76.4 50.4
1829 43.0 49.4 72.3 95.0 67.5 73.9 90.8 78.3 52.8
1830 52.2 72.1 84.6 107.1 66.3 65.1 43.9 50.7 62.1
1831 47.5 50.1 93.4 54.6 38.1 33.4 45.2 54.9 37.9
Oct Nov Dec
1749 75.5 158.6 85.2
1750 65.7 63.3 75.4
1751 23.2 28.5 44.0
1752 46.6 37.6 40.0
1753 25.0 20.0 6.7
1754 24.1 13.2 4.2
1755 23.7 6.8 20.0
1756 14.3 17.0 9.4
1757 32.5 64.7 33.5
1758 37.7 43.0 43.0
1759 59.7 46.3 57.0
1760 50.6 59.7 61.0
1761 88.7 89.7 46.0
1762 69.3 77.8 77.2
1763 46.3 60.9 61.4
1764 28.0 26.0 25.7
1765 14.0 14.0 13.0
1766 5.0 5.7 19.2
1767 44.1 54.7 53.3
1768 77.8 90.6 111.8
1769 158.2 148.1 112.0
1770 103.6 132.2 102.3
1771 90.0 99.7 95.7
1772 78.6 61.3 64.0
1773 26.3 40.9 43.2
1774 14.0 17.7 12.2
1775 5.6 15.1 7.9
1776 30.0 35.0 40.0
1777 106.5 146.0 157.3
1778 156.3 150.3 105.0
1779 124.0 114.0 110.0
1780 77.0 60.0 58.7
1781 27.3 67.0 35.2
1782 23.2 31.5 30.0
1783 8.0 15.0 10.5
1784 8.0 17.0 14.0
1785 47.2 40.2 27.3
1786 112.3 116.0 112.7
1787 157.0 141.5 174.0
1788 142.0 94.7 129.5
1789 89.7 134.0 135.5
1790 84.3 82.0 74.0
1791 61.7 67.0 66.0
1792 59.0 57.0 56.0
1793 47.0 44.0 45.7
1794 28.5 67.4 51.4
1795 19.5 25.0 18.0
1796 11.0 8.4 5.1
1797 6.9 5.8 3.0
1798 1.5 12.5 9.9
1799 4.6 2.7 8.6
1800 12.3 10.5 40.1
1801 32.6 39.8 48.2
1802 38.5 34.5 50.0
1803 54.3 51.0 48.0
1804 62.3 61.0 60.0
1805 29.4 41.0 38.3
1806 27.0 25.0 24.0
1807 8.0 2.6 0.0
1808 4.7 10.5 12.3
1809 0.0 0.0 0.0
1810 0.0 0.0 0.0
1811 6.1 0.8 1.1
1812 3.9 7.9 10.1
1813 27.8 16.7 14.3
1814 19.3 14.5 20.1
1815 33.5 37.2 65.0
1816 56.4 38.1 29.9
1817 25.6 28.9 28.4
1818 31.7 10.9 25.8
1819 27.5 25.1 30.6
1820 9.0 7.9 9.7
1821 18.8 4.4 0.0
1822 0.4 0.0 0.0
1823 0.0 0.0 20.4
1824 25.2 0.0 0.8
1825 15.6 11.7 22.0
1826 50.6 39.5 68.1
1827 57.2 48.2 46.1
1828 54.7 57.0 46.6
1829 57.2 67.6 56.5
1830 84.4 81.2 82.1
1831 46.2 43.5 28.9
[ reached getOption("max.print") -- omitted 152 rows ]
> presidents # 美国总统支持率
Qtr1 Qtr2 Qtr3 Qtr4
1945 NA 87 82 75
1946 63 50 43 32
1947 35 60 54 55
1948 36 39 NA NA
1949 69 57 57 51
1950 45 37 46 39
1951 36 24 32 23
1952 25 32 NA 32
1953 59 74 75 60
1954 71 61 71 57
1955 71 68 79 73
1956 76 71 67 75
1957 79 62 63 57
1958 60 49 48 52
1959 57 62 61 66
1960 71 62 61 57
1961 72 83 71 78
1962 79 71 62 74
1963 76 64 62 57
1964 80 73 69 69
1965 71 64 69 62
1966 63 46 56 44
1967 44 52 38 46
1968 36 49 35 44
1969 59 65 65 56
1970 66 53 61 52
1971 51 48 54 49
1972 49 61 NA NA
1973 68 44 40 27
1974 28 25 24 24
看了这两个时间序列数据集,我们来看一下ta的性质:
> class(sunspots)
[1] "ts"
> class(presidents)
[1] "ts"
> presidents$Qtr1 # 可见时间序列不能索引列
Error in presidents$Qtr1 : $ operator is invalid for atomic vectors
我们上面讲的时间序列都和数据框很像,然后我们看一种标准的时间序列格式:
> airmiles
Time Series:
Start = 1937
End = 1960
Frequency = 1
[1] 412 480 683 1052 1385 1418 1634 2178 3362
[10] 5948 6109 5981 6753 8003 10566 12528 14760 16769
[19] 19819 22362 25340 25343 29269 30514
其中表示了从start到end中在frequency频率中的每个点的数据。
日期和时间专门有一个类date:
> Sys.Date() # 获取当前系统时间
[1] "2021-08-03"
> class(Sys.Date())
[1] "Date"
> time <- '2021-08-03'
> class(time)
[1] "character"
> as.Date(time) # 转化为日期类
[1] "2021-08-03"
> class(as.Date(time))
[1] "Date"
> as.Date('08-03-2021', format = '%m-%d-%Y') # format参数用于确定日期的格式
[1] "2021-08-03"
> as.Date('08,03,2021', format = '%m,%d,%Y')
[1] "2021-08-03"
date类也和普通的数据类一样,可以用一些用在数值上的函数:
> seq(as.Date('2001-01-01'), as.Date('2008-08-08'), by = 111) # 用于在区间内取值,因为是日期类,自然用日期表示
[1] "2001-01-01" "2001-04-22" "2001-08-11" "2001-11-30"
[5] "2002-03-21" "2002-07-10" "2002-10-29" "2003-02-17"
[9] "2003-06-08" "2003-09-27" "2004-01-16" "2004-05-06"
[13] "2004-08-25" "2004-12-14" "2005-04-04" "2005-07-24"
[17] "2005-11-12" "2006-03-03" "2006-06-22" "2006-10-11"
[21] "2007-01-30" "2007-05-21" "2007-09-09" "2007-12-29"
[25] "2008-04-18" "2008-08-07"
我们用ts函数可以很方便的把数据变成时间序列的数据:
> ls <- round(runif(50, 0, 100))
> ls
[1] 19 15 41 7 33 6 30 89 75 38 5 45 14 24
[15] 55 6 32 25 60 85 49 63 23 98 78 99 25 73
[29] 15 33 26 68 30 90 99 91 27 39 49 83 81 83
[43] 60 72 38 30 60 100 17 27
> ts(ls, start = c(2012, 8), end = c(2016, 8), frequency = 12)
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
2012 19 15 41 7 33
2013 6 30 89 75 38 5 45 14 24 55 6 32
2014 25 60 85 49 63 23 98 78 99 25 73 15
2015 33 26 68 30 90 99 91 27 39 49 83 81
2016 83 60 72 38 30 60 100 17
> ts(ls, start = c(2012, 4), end = c(2016, 4), frequency = 4)
Qtr1 Qtr2 Qtr3 Qtr4
2012 19
2013 15 41 7 33
2014 6 30 89 75
2015 38 5 45 14
2016 24 55 6 32
> ts(ls, start = c(2012), end = c(2016), frequency = 1)
Time Series:
Start = 2012
End = 2016
Frequency = 1
[1] 19 15 41 7 33
在上面frequency中取值为12、4、1,分别对应为月、季度、年(很好记,就是月、季度、年的数量)。我们一般不以天来计算。
但是有可能出的是什么问题呢?就是取值为12、4、1的参数意义不完全一样,在这里解析一下:
> ts(ls, start = c(2012, 8), end = c(2016, 8), frequency = 12)
# 这里的参数表示月份和第几个月
> ts(ls, start = c(2012, 4), end = c(2016, 4), frequency = 4)
# 这里的参数表示月份和第几个季度,如果超过四,就忘下一年算,如2012、8,就是2013年的第四季度
> ts(ls, start = c(2012), end = c(2016), frequency = 1)
# 这里的参数表示年份,如果多加了一个参数,就会往后按加的数字移动相应的年份
为啥会有缺失数据?很正常,要么是故障导致的数据丢失,要么就是根本没有收集这种数据。我们在R中统一使用NA表示缺失值。
这里特别讲一下缺失值:缺失值是指不知道的值, 表示没有数据,可能是0也可能是其他任何的值。什么意思呢?看我例子:
> 1 + NA # 1+不知道的值,也不知道是多少
[1] NA
> NA == 0 # 不知道的值,不知道是不是等于0
[1] NA
所以在我们对NA进行处理的时候永远都是NA,这就会给我们造成很多麻烦。比如我们在这里举个例子:
> sum(c(0, 1:50)) # 求0~50的和
[1] 1275
> sum(c(NA, 1:50)) # 把0换成NA求和
[1] NA
这里我们经常就得不到想要的结果,因为我们大多数时候是想要不管NA继续计算1~50的和的,所以为了这样计算,我们可以这样处理:
> sum(c(NA, 1:50), na.rm = T) # 将NA的数据都移除
[1] 1275
> mean(c(NA, 1:50), na.rm = T) # 求中位数
[1] 25.5
同时我们还可以从上面知道,我们求平均数的时候,用的是1到50的和,除以的也是50。代表了在计算的时候,我们是彻底没有管过NA。
我们已经初步了解了NA是什么,然后我们要在数据中判断NA是否存在,我们怎么做呢?其实R中内置了很多is函数,我们可以使用is函数判断很多数据类型,我们来试一试:
> library(VIM) # 加载VIM包,没有就下,下的不成功看安装教程,win应该下的很轻松
VIM is ready to use.
Suggestions and bug-reports can be submitted at: https://github.com/statistikat/VIM/issues
Attaching package: ‘VIM’
The following object is masked from ‘package:datasets’:
sleep
> head(sleep)
BodyWgt BrainWgt NonD Dream Sleep Span Gest Pred Exp
1 6654.000 5712.0 NA NA 3.3 38.6 645 3 5
2 1.000 6.6 6.3 2.0 8.3 4.5 42 3 1
3 3.385 44.5 NA NA 12.5 14.0 60 1 1
4 0.920 5.7 NA NA 16.5 NA 25 5 2
5 2547.000 4603.0 2.1 1.8 3.9 69.0 624 3 5
6 10.550 179.5 9.1 0.7 9.8 27.0 180 4 4
Danger
1 3
2 3
3 1
4 3
5 4
6 4
> head(is.na(sleep))
BodyWgt BrainWgt NonD Dream Sleep Span Gest Pred
[1,] FALSE FALSE TRUE TRUE FALSE FALSE FALSE FALSE
[2,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[3,] FALSE FALSE TRUE TRUE FALSE FALSE FALSE FALSE
[4,] FALSE FALSE TRUE TRUE FALSE TRUE FALSE FALSE
[5,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[6,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
Exp Danger
[1,] FALSE FALSE
[2,] FALSE FALSE
[3,] FALSE FALSE
[4,] FALSE FALSE
[5,] FALSE FALSE
[6,] FALSE FALSE
然后可以发现,sleep这个数据集里面是有很多NA值的,这个时候我们如果去计算行列的总和就会发生很多问题:
> colSums(sleep)
BodyWgt BrainWgt NonD Dream Sleep Span
12324.98 17554.32 NA NA NA NA
Gest Pred Exp Danger
NA 178.00 150.00 162.00
> rowSums(sleep)
[1] NA 77.700 NA NA 7862.800 428.650
[7] 96.723 776.800 152.900 794.560 163.825 1221.800
[13] NA NA 66.575 129.200 79.685 163.000
[19] NA NA NA 333.260 55.820 NA
[25] 778.400 NA 77.701 110.540 1578.800 NA
[31] NA 53.445 117.060 1768.000 NA NA
[37] 57.023 65.978 67.800 179.600 NA 207.980
[43] 349.000 75.420 542.800 95.400 NA 61.280
[49] 139.035 405.000 264.250 274.400 NA 424.100
[55] NA NA 99.600 239.600 89.504 327.790
[61] 67.200 NA
对吧,里面有很多值就是NA,要计算简单,在函数里面加上na.rm为真就好了,但是我们是怎么处理这些数据的呢?这里我们可以用到na.omit
函数,这个函数可以将有NA的数据集去除NA:
> na.omit(c(1:5, NA, 6:10, NA))
[1] 1 2 3 4 5 6 7 8 9 10
attr(,"na.action")
[1] 6 12
attr(,"class")
[1] "omit"
> na.omit(sleep)
BodyWgt BrainWgt NonD Dream Sleep Span Gest Pred Exp
2 1.000 6.60 6.3 2.0 8.3 4.5 42.0 3 1
5 2547.000 4603.00 2.1 1.8 3.9 69.0 624.0 3 5
6 10.550 179.50 9.1 0.7 9.8 27.0 180.0 4 4
7 0.023 0.30 15.8 3.9 19.7 19.0 35.0 1 1
8 160.000 169.00 5.2 1.0 6.2 30.4 392.0 4 5
9 3.300 25.60 10.9 3.6 14.5 28.0 63.0 1 2
10 52.160 440.00 8.3 1.4 9.7 50.0 230.0 1 1
11 0.425 6.40 11.0 1.5 12.5 7.0 112.0 5 4
12 465.000 423.00 3.2 0.7 3.9 30.0 281.0 5 5
15 0.075 1.20 6.3 2.1 8.4 3.5 42.0 1 1
16 3.000 25.00 8.6 0.0 8.6 50.0 28.0 2 2
17 0.785 3.50 6.6 4.1 10.7 6.0 42.0 2 2
18 0.200 5.00 9.5 1.2 10.7 10.4 120.0 2 2
22 27.660 115.00 3.3 0.5 3.8 20.0 148.0 5 5
23 0.120 1.00 11.0 3.4 14.4 3.9 16.0 3 1
25 85.000 325.00 4.7 1.5 6.2 41.0 310.0 1 3
27 0.101 4.00 10.4 3.4 13.8 9.0 28.0 5 1
28 1.040 5.50 7.4 0.8 8.2 7.6 68.0 5 3
29 521.000 655.00 2.1 0.8 2.9 46.0 336.0 5 5
32 0.005 0.14 7.7 1.4 9.1 2.6 21.5 5 2
33 0.010 0.25 17.9 2.0 19.9 24.0 50.0 1 1
34 62.000 1320.00 6.1 1.9 8.0 100.0 267.0 1 1
37 0.023 0.40 11.9 1.3 13.2 3.2 19.0 4 1
38 0.048 0.33 10.8 2.0 12.8 2.0 30.0 4 1
39 1.700 6.30 13.8 5.6 19.4 5.0 12.0 2 1
40 3.500 10.80 14.3 3.1 17.4 6.5 120.0 2 1
42 0.480 15.50 15.2 1.8 17.0 12.0 140.0 2 2
43 10.000 115.00 10.0 0.9 10.9 20.2 170.0 4 4
44 1.620 11.40 11.9 1.8 13.7 13.0 17.0 2 1
45 192.000 180.00 6.5 1.9 8.4 27.0 115.0 4 4
46 2.500 12.10 7.5 0.9 8.4 18.0 31.0 5 5
48 0.280 1.90 10.6 2.6 13.2 4.7 21.0 3 1
49 4.235 50.40 7.4 2.4 9.8 9.8 52.0 1 1
50 6.800 179.00 8.4 1.2 9.6 29.0 164.0 2 3
51 0.750 12.30 5.7 0.9 6.6 7.0 225.0 2 2
52 3.600 21.00 4.9 0.5 5.4 6.0 225.0 3 2
54 55.500 175.00 3.2 0.6 3.8 20.0 151.0 5 5
57 0.900 2.60 11.0 2.3 13.3 4.5 60.0 2 1
58 2.000 12.30 4.9 0.5 5.4 7.5 200.0 3 1
59 0.104 2.50 13.2 2.6 15.8 2.3 46.0 3 2
60 4.190 58.00 9.7 0.6 10.3 24.0 210.0 4 3
61 3.500 3.90 12.8 6.6 19.4 3.0 14.0 2 1
Danger
2 3
5 4
6 4
7 1
8 4
9 1
10 1
11 4
12 5
15 1
16 2
17 2
18 2
22 5
23 2
25 1
27 3
28 4
29 5
32 4
33 1
34 1
37 3
38 3
39 1
40 1
42 2
43 4
44 2
45 4
46 5
48 3
49 1
50 2
51 2
52 3
54 5
57 2
58 3
59 2
60 4
61 1
我们看到我们删除向量中NA的时候成功删除了,还多了删除的位置。删除数据框的时候也成功了,而且把含有NA的这一行也全部删除了:
> length(rownames(sleep))
[1] 62
> length(rownames(na.omit(sleep)))
[1] 42
也可以像is.na一样,用is.nan和is.inf来判断。
ps:
R中包含了高效用于处理缺失值的包,如VIM包等,详细的可以再去学,基础这里就不介绍了。
R处理字符串用的最多的就是正则表达式,但是处理文本用python也挺好的,这里可以不用R
我们看下面的代码,简单学几个函数:
> nchar('Hello, World!') # 统计字符串长度
[1] 13
> month.name
[1] "January" "February" "March" "April"
[5] "May" "June" "July" "August"
[9] "September" "October" "November" "December"
> nchar(month.name) # 统计字符串向量每个字符串长度
[1] 7 8 5 5 3 4 4 6 9 7 8 8
> length(month.name) # 我才是用来统计向量长度的
[1] 12
> paste('han', 'han') # 连接字符串
[1] "han han"
> paste('han', 'han', sep = '') # 也可以设置连接符
[1] "hanhan"
> paste(month.name, 'hanhan') # 向量中的每个字符串与字符串相连
[1] "January hanhan" "February hanhan" "March hanhan"
[4] "April hanhan" "May hanhan" "June hanhan"
[7] "July hanhan" "August hanhan" "September hanhan"
[10] "October hanhan" "November hanhan" "December hanhan"
> substr(month.name, 1, 3) # 截取字符串,从1开始,取3个
[1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep"
[10] "Oct" "Nov" "Dec"
> month.abb
[1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep"
[10] "Oct" "Nov" "Dec"
> toupper(month.abb) # 全转大写
[1] "JAN" "FEB" "MAR" "APR" "MAY" "JUN" "JUL" "AUG" "SEP"
[10] "OCT" "NOV" "DEC"
> tolower(month.abb) # 全转小写
[1] "jan" "feb" "mar" "apr" "may" "jun" "jul" "aug" "sep"
[10] "oct" "nov" "dec"
> str <- 'I am hanhan'
> strsplit(str, ' ') # 按自定义分割符,分割字符串
[[1]]
[1] "I" "am" "hanhan"
> strsplit(c(str, str, str), ' ') # 分割多个字符串
[[1]]
[1] "I" "am" "hanhan"
[[2]]
[1] "I" "am" "hanhan"
[[3]]
[1] "I" "am" "hanhan"
> face <- 1: 13
> suit <- c('spades', 'clubs', 'hearts', 'diamonds')
> outer (suit, face, FUN = paste) # 笛卡尔积,采用连接函数
[,1] [,2] [,3] [,4]
[1,] "spades 1" "spades 2" "spades 3" "spades 4"
[2,] "clubs 1" "clubs 2" "clubs 3" "clubs 4"
[3,] "hearts 1" "hearts 2" "hearts 3" "hearts 4"
[4,] "diamonds 1" "diamonds 2" "diamonds 3" "diamonds 4"
[,5] [,6] [,7] [,8]
[1,] "spades 5" "spades 6" "spades 7" "spades 8"
[2,] "clubs 5" "clubs 6" "clubs 7" "clubs 8"
[3,] "hearts 5" "hearts 6" "hearts 7" "hearts 8"
[4,] "diamonds 5" "diamonds 6" "diamonds 7" "diamonds 8"
[,9] [,10] [,11] [,12]
[1,] "spades 9" "spades 10" "spades 11" "spades 12"
[2,] "clubs 9" "clubs 10" "clubs 11" "clubs 12"
[3,] "hearts 9" "hearts 10" "hearts 11" "hearts 12"
[4,] "diamonds 9" "diamonds 10" "diamonds 11" "diamonds 12"
[,13]
[1,] "spades 13"
[2,] "clubs 13"
[3,] "hearts 13"
[4,] "diamonds 13"
> outer (suit, face, FUN = paste, sep = '--') # 既然用了连接函数,自然也可以换连接符
[,1] [,2] [,3] [,4]
[1,] "spades--1" "spades--2" "spades--3" "spades--4"
[2,] "clubs--1" "clubs--2" "clubs--3" "clubs--4"
[3,] "hearts--1" "hearts--2" "hearts--3" "hearts--4"
[4,] "diamonds--1" "diamonds--2" "diamonds--3" "diamonds--4"
[,5] [,6] [,7] [,8]
[1,] "spades--5" "spades--6" "spades--7" "spades--8"
[2,] "clubs--5" "clubs--6" "clubs--7" "clubs--8"
[3,] "hearts--5" "hearts--6" "hearts--7" "hearts--8"
[4,] "diamonds--5" "diamonds--6" "diamonds--7" "diamonds--8"
[,9] [,10] [,11]
[1,] "spades--9" "spades--10" "spades--11"
[2,] "clubs--9" "clubs--10" "clubs--11"
[3,] "hearts--9" "hearts--10" "hearts--11"
[4,] "diamonds--9" "diamonds--10" "diamonds--11"
[,12] [,13]
[1,] "spades--12" "spades--13"
[2,] "clubs--12" "clubs--13"
[3,] "hearts--12" "hearts--13"
[4,] "diamonds--12" "diamonds--13"
先举个例子,我们要将一个全小写的月份改成首字母大写。我们这时候可以使用到sub
和gsub
函数。差别是什么呢?sub
是一次替换,gsub
是全局替换。
> gsub('^(\\w)', '\\U\\1', tolower(month.abb)) # 正则替换,gsub(被替换的串,替换的串,原串)
[1] "Ujan" "Ufeb" "Umar" "Uapr" "Umay" "Ujun" "Ujul" "Uaug"
[9] "Usep" "Uoct" "Unov" "Udec"
> gsub('^(\\w)', '\\U\\1', tolower(month.abb), perl = T) # 我们是perl类型正则表达式,所以需要perl=T
[1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep"
[10] "Oct" "Nov" "Dec"
> gsub('^(\\w)', '\\L\\1', toupper(month.abb), perl = T) # 同理小写
[1] "jAN" "fEB" "mAR" "aPR" "mAY" "jUN" "jUL" "aUG" "sEP"
[10] "oCT" "nOV" "dEC"
除了gsub
的匹配函数,我们也常用grep
和match
函数,这两个又有什么差别呢?很简单,就是grep
可以用正则,match
函数只能直接匹配:
> cmp
[1] "han+" "hanhan" "handsome" "def"
> grep('han+', cmp) # 正则查找
[1] 1 2 3
> grep('han+', cmp, fixed = F) # fixed=F表示可以正则
[1] 1 2 3
> grep('han+', cmp, fixed = T) # 关闭正则
[1] 1
> match('han+', cmp) # 查找'han+'字符串,无正则
[1] 1
> match('han', cmp) # 查找'han'字符串,没有,因为match类似于%in%
[1] NA
手写数据是最无聊也是最工具人的操作了,其实做几个变量,并且转换为数据框就完成了,没有啥技术性:
> # 输入病例数据变量
> PaientID <- c(1: 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')
> # 根据变量构造数据框
> dop <- data.frame(PaientID, AdmDate, Age, Diabetes, Status)
> dop
patientID admdate age diabetes status
1 1 10/15/2019 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
然后就要讲到一个操作,也就是和Excel一样的图形化界面(不过完全没有Excel好用,不如在Excel里做好了再导入R):
data <- edit(data)
保存只要关闭退出就好咯,但是edit是返回一个结果,所以必须要赋值给一个新的变量哦。
然后这里必须要备注一下了,win系统当然是可以直接打开的,但是Mac用户会发现我们无法运行。因为Mac系统缺乏这样一个图形化的界面环境,所以要先下载一个软件(XQuartz)才能开始使用,下完只要运行指令就会自动调用这个软件咯(第二个让我更愿意Excel的原因是,这个软件界面挺丑der,用着还不舒服)。
数据库读取可以使用一些数据库的库进行连接,但由于为不用数据库连接,目前也没用常用数据库,所以要用到以后再来补档。
辛酸故事:我是想下RODBC包进行连接我的mysql数据库试试的,但我试试就逝世了。我根本安装不上,正如我的R包安装血泪史一样。所以我暂时放弃了。
读取txt文件,首先需要有一个txt文件,所以在这我先给出一个文件:
将这个文件读入,我们只需要进行下面的操作,因为对于普通的txt文件R默认是有读入方法的,所以不用下载包:
> df <- read.table('./MyData/input.txt')
> head(df) # 技巧,默认用于显示data.frame前6行
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(df) # 我当然也可以尾6行
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(df, 3) # 或者我只想看3行
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
这里要注意一下就是我的文件是放在默认目录下的,所以我用的相对路径。
但除了上面这种用空格隔开数据的txt文本数据,我们在很早也常用csv文件,csv文件很简单,就相当于是将我们上面看见的这种txt文本文件的数据用逗号隔开罢了:
所以读入的时候和读取txt文件用的是同一个函数(或者直接用读csv的函数),但是读入有个什么限制呢?很容易理解,就是我们需要用逗号分隔罢了:
> df <- read.table('./MyData/input.csv') # 直接读的错误读法
> head(df)
V1
1
2 Mazda RX4
3 Mazda RX4 Wag
4 Datsun 710
5 Hornet 4 Drive
6 Hornet Sportabout
V2
1 ,"mpg","cyl","disp","hp","drat","wt","qsec","vs","am","gear","carb"
2 ,21,6,160,110,3.9,2.62,16.46,0,1,4,4
3 ,21,6,160,110,3.9,2.875,17.02,0,1,4,4
4 ,22.8,4,108,93,3.85,2.32,18.61,1,1,4,1
5 ,21.4,6,258,110,3.08,3.215,19.44,1,0,3,1
6 ,18.7,8,360,175,3.15,3.44,17.02,0,0,3,2
> df <- read.table('./MyData/input.csv', sep = ',') # 我们将分隔符改为逗号,读入正确,但是列号错了
> head(df)
V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
1 mpg cyl disp hp drat wt qsec vs am
2 Mazda RX4 21 6 160 110 3.9 2.62 16.46 0 1
3 Mazda RX4 Wag 21 6 160 110 3.9 2.875 17.02 0 1
4 Datsun 710 22.8 4 108 93 3.85 2.32 18.61 1 1
5 Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0
6 Hornet Sportabout 18.7 8 360 175 3.15 3.44 17.02 0 0
V11 V12
1 gear carb
2 4 4
3 4 4
4 4 1
5 3 1
6 3 2
> df <- read.table('./MyData/input.csv', sep = ',', header = T) # 加上了同意将第一行作为列号
> head(df)
X mpg cyl disp hp drat wt qsec vs am
1 Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1
2 Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1
3 Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1
4 Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0
5 Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0
6 Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0
gear carb
1 4 4
2 4 4
3 4 1
4 3 1
5 3 2
6 3 1
> df <- read.csv('./MyData/input.csv') # 或者直接用读csv的函数
> head(df)
X mpg cyl disp hp drat wt qsec vs am
1 Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1
2 Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1
3 Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1
4 Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0
5 Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0
6 Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0
gear carb
1 4 4
2 4 4
3 4 1
4 3 1
5 3 2
6 3 1
这个函数中还有许多参数可以使用,例如skip
参数可以用于跳过前面指定数量的行,nrow
用于确定读取的行数,配合可以取得某一段的数据。这些都可以使用?read.table
去查看参数的使用方法。还有比如na.string
,用于确定数据中的缺失值,因为一个数据集中的缺失值不一定都表示为NA
,比如为nothing
,我们就可以用这个参数将这个符号替换为缺失值。
我们在上面使用了read.csv
的方法,其实这个方法和read.table
没有本质的差别,主要就是改了一个分隔符,都是从read.table
演变而来的。还有read.fwf
用来确定每一个变量的占位长度。都可以查阅文档(read.fwf
用的少就不讲)。
除此之外还有用于提取剪切板的方法,我们也可以在剪切板中保存数据并读取,在这里Mac用户和win用户就有差别了,因为两边的剪切板表达方式不太一样:
> df <- read.csv(pipe('pbpaste')) # Mac
> df
X mpg cyl disp hp drat wt qsec vs am
1 Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1
2 Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1
3 Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1
4 Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0
5 Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0
6 Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0
7 Duster 360 14.3 8 360 245 3.21 3.570 15.84 0 0
gear carb
1 4 4
2 4 4
3 4 1
4 3 1
5 3 2
6 3 1
7 3 4
> df <- read.csv('clipboard') # win
> df <- readClipboard() # win
还有一些别的函数用于读取,不过多讲解,就演示一下:
> readLines('./MyData/input.csv', n = 5) # 用字符串读出指定行数
[1] "\"\",\"mpg\",\"cyl\",\"disp\",\"hp\",\"drat\",\"wt\",\"qsec\",\"vs\",\"am\",\"gear\",\"carb\""
[2] "\"Mazda RX4\",21,6,160,110,3.9,2.62,16.46,0,1,4,4"
[3] "\"Mazda RX4 Wag\",21,6,160,110,3.9,2.875,17.02,0,1,4,4"
[4] "\"Datsun 710\",22.8,4,108,93,3.85,2.32,18.61,1,1,4,1"
[5] "\"Hornet 4 Drive\",21.4,6,258,110,3.08,3.215,19.44,1,0,3,1"
html网页表格本就是为了让用户进行阅读才放的文件,可以用XML以及多个包进行提取,但是不建议这样搞,所以略了略了
一切花里胡哨格式的文件都建议先转换为Excel文件再进行读取。
其实写入和读取没有太大的差别,我们直接上例子:
> df <- read.csv('./MyData/input.csv')
> head(df)
X mpg cyl disp hp drat wt qsec vs am
1 Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1
2 Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1
3 Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1
4 Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0
5 Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0
6 Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0
gear carb
1 4 4
2 4 4
3 4 1
4 3 1
5 3 2
6 3 1
> write.table(df, 'test.txt')
> write.csv(df, 'test.csv')
可以看到我们都正常的写入了,当然写个啥列表什么的也没问题咯:
> 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 1243 890 350 407 286 280 525 720 390 250 327 230 265 850 210 630 260 230 360 730 600 306 390 420 291 710 340 217 281 352 259 250 470 680 570 350 300 560 900 625 332 2348 1171 3710 2315 2533 780 280 410 460 260 255 431 350 760 618 338 981 1306 500 696 605 250 411 1054 735 233 435 490 310 460 383 375 1270 545 445 1885 380 300 380 377 425 276 210 800 420 350 360 538 1100 1205 314 237 610 360 540 1038 424 310 300 444 301 268 620 215 652 900 525 246 360 529 500 720 270 430 671 1770
> write(rivers, 'rivers.txt')
是吧,莫得问题~
但是在对csv文件进行操作的时候有一个很大的问题,我们来看一下:
> df <- read.csv('test.csv')
> head(df)
X.1 X mpg cyl disp hp drat wt qsec vs
1 1 Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0
2 2 Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0
3 3 Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1
4 4 Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1
5 5 Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0
6 6 Valiant 18.1 6 225 105 2.76 3.460 20.22 1
am gear carb
1 1 4 4
2 1 4 4
3 1 4 1
4 0 3 1
5 0 3 2
6 0 3 1
> write.csv(df, 'test.csv')
> df <- read.csv('test.csv')
> head(df)
X.2 X.1 X mpg cyl disp hp drat wt qsec
1 1 1 Mazda RX4 21.0 6 160 110 3.90 2.620 16.46
2 2 2 Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02
3 3 3 Datsun 710 22.8 4 108 93 3.85 2.320 18.61
4 4 4 Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44
5 5 5 Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02
6 6 6 Valiant 18.1 6 225 105 2.76 3.460 20.22
vs am gear carb
1 0 1 4 4
2 0 1 4 4
3 1 1 4 1
4 1 0 3 1
5 0 0 3 2
6 1 0 3 1
我们会发现,我们每次对csv文件进行一次读写,就对多一列行号,为啥呢?因为每次都会把行号当成数据列读进去又当成数据读出来呀。反复几次就多了很多多余的东西了。
我们这么解决:
> head(df) # 先有一份最原始的数据
X mpg cyl disp hp drat wt qsec vs am
1 Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1
2 Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1
3 Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1
4 Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0
5 Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0
6 Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0
gear carb
1 4 4
2 4 4
3 4 1
4 3 1
5 3 2
6 3 1
> write.csv(df, 'test.csv', row.names = F) # 列名参数置否
就没问题了~
还有一些参数,像追加之类的:
> write.table(iris, 'test.csv', sep = ',', append = T) # 不覆盖表格并在后面添加
第一种方法其实就是,把xlsx文件保存为txt或csv就可以了,用上面的txt类方法就可以读取了。当然读剪切板也行。
然后就是安装包直接对xlsx文件进行读写了,我一般使用openxlsx包,这个包简单方便(还有XLConnect包可以用,但是我Mac因为可能是java环境的问题装不上,我就放弃了):
> library(openxlsx)
> df <- read.xlsx('./MyData/data.xlsx') # 直接提取表格
> head(df)
X1 mpg cyl disp hp drat wt qsec vs am
1 Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1
2 Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1
3 Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1
4 Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0
5 Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0
6 Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0
gear carb
1 4 4
2 4 4
3 4 1
4 3 1
5 3 2
6 3 1
> write.xlsx(df, 'test.xlsx') # 直接写入表格
当然还有一些参数可以用咯,我们来康康,因为不难,所以不逐个解析:
> df <- read.xlsx('./MyData/data.xlsx', colNames = F) # 不把第一行作为列明
> head(df, 3)
X1 X2 X3 X4 X5 X6 X7 X8 X9 X10
1 mpg cyl disp hp drat wt qsec vs am
2 Mazda RX4 21.0 6.0 160.0 110.0 3.9 2.62 16.46 0.0 1.0
3 Mazda RX4 Wag 21.0 6.0 160.0 110.0 3.9 2.875 17.02 0.0 1.0
X11 X12
1 gear carb
2 4.0 4.0
3 4.0 4.0
> df <- read.xlsx('./MyData/data.xlsx', rowNames = T) # 将第一列作为行名
> head(df, 3)
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
Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4
carb
Mazda RX4 4
Mazda RX4 Wag 4
Datsun 710 1
> df <- read.xlsx('./MyData/data.xlsx', rows = c(8: 12), cols = c(1: 3), colNames = F) # 选取行列
> df
X1 X2 X3
1 Duster 360 14.3 8
2 Merc 240D 24.4 4
3 Merc 230 22.8 4
4 Merc 280 19.2 6
5 Merc 280C 17.8 6
> write.xlsx(list(df, df), 'test.xlsx') # 输出为两个sheet
其实原本Excel读取是可以多讲一点的,因为读取Excel分为多步骤和单步骤,多步骤有助于代码的理解,不过我没讲。
简单来说就是,读文件分为,建立对象,读取文件,读取表,读取数据;写对象分为,建立对象,写文件,写表,写数据。
但是作为应用知道怎么用就好啦。然后学过python的同志应该也会更了解,数据分析还是python比R好,所以要看就去康python吧。或者直接学Excel哈哈哈
R格式的文件,很简单就能理解,是R专门的文件格式,好处是什么呢?很好理解,我们可以将数据原样的转移到文件里面。因为如果保存为别的格式的文件,总会有一些数据丢失的。
怎么存呢?就很简单:
> class(state.x77)
[1] "matrix" "array"
> mx <- state.x77
> head(mx)
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
Arkansas 2110 3378 1.9 70.66 10.1
California 21198 5114 1.1 71.71 10.3
Colorado 2541 4884 0.7 72.06 6.8
HS Grad Frost Area
Alabama 41.3 20 50708
Alaska 66.7 152 566432
Arizona 58.1 15 113417
Arkansas 39.9 65 51945
California 62.6 20 156361
Colorado 63.9 166 103766
> saveRDS(mx, 'mx.RDS')
这样就成功存进去了,既然我刚刚说了可以不丢失的保存,那我们再读出来试试:
> mx <- readRDS("~/Documents/Rstudio/mx.RDS")
> class(mx)
[1] "matrix" "array"
> head(mx)
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
Arkansas 2110 3378 1.9 70.66 10.1
California 21198 5114 1.1 71.71 10.3
Colorado 2541 4884 0.7 72.06 6.8
HS Grad Frost Area
Alabama 41.3 20 50708
Alaska 66.7 152 566432
Arizona 58.1 15 113417
Arkansas 39.9 65 51945
California 62.6 20 156361
Colorado 63.9 166 103766
没有任何问题~
关于R的数据文件,除了用于保存数据的.RDS,还有==.RData文件==,我们R的工作目录下就会自动生成的这个文件是啥呢?
其实.RData这个文件是用于保存我们工作区中变量的,同样,我们也可以自己制作以.RData为后缀的数据文件,同时使用时会自动加载这里面的数据。
> save(iris, file = 'iris.RData')
> load("~/Documents/Rstudio/iris.RData")
这就保存了想要的变量,然后保存全部的也很简单:
> save.image(file = 'all.RData')
> load("~/Documents/Rstudio/all.RData")
本章完~其他R内容同专栏更新