tidyr包的作者是Hadley Wickham。这个包常跟dplyr结合使用。
本文将演示tidyr包中下述四个函数的用法:
gather—宽数据转为长数据。类似于reshape2包中的melt函数
spread—长数据转为宽数据。类似于reshape2包中的cast函数
unit—多列合并为一列
separate—将一列分离为多列
下面使用datasets包中的mtcars数据集做演示。
library(tidyr)
library(dplyr)
head(mtcars)
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
为方便处理,在数据集中增加一列car
mtcars$car <- rownames(mtcars)
mtcars <- mtcars[, c(12, 1:11)]
gather
gather的调用格式为:
gather(data, key, value, ..., na.rm = FALSE, convert = FALSE)
这里,...表示需要聚合的指定列。
与reshape2包中的melt函数一样,得到如下结果:
mtcarsNew <- mtcars %>% gather(attribute, value, -car)
head(mtcarsNew)
car attribute value
1 Mazda RX4 mpg 21.0
2 Mazda RX4 Wag mpg 21.0
3 Datsun 710 mpg 22.8
4 Hornet 4 Drive mpg 21.4
5 Hornet Sportabout mpg 18.7
6 Valiant mpg 18.1
tail(mtcarsNew)
car attribute value
347 Porsche 914-2 carb 2
348 Lotus Europa carb 2
349 Ford Pantera L carb 4
350 Ferrari Dino carb 6
351 Maserati Bora carb 8
352 Volvo 142E carb 2
如你所见,除了car列外,其余列聚合成两列,分别命名为attribute和value。
tidyr很好的一点是可以只gather若干列而其他列保持不变。如果你想gather在map和gear之间的所有列而保持carb和car列不变,可以像下面这样做:
mtcarsNew <- mtcars %>% gather(attribute, value, mpg:gear)
head(mtcarsNew)
car carb attribute value
1 Mazda RX4 4 mpg 21.0
2 Mazda RX4 Wag 4 mpg 21.0
3 Datsun 710 1 mpg 22.8
4 Hornet 4 Drive 1 mpg 21.4
5 Hornet Sportabout 2 mpg 18.7
6 Valiant 1 mpg 18.1
spread
spread的调用格式为:
spread(data, key, value, fill = NA, convert = FALSE, drop = TRUE)
与reshape2包中的cast函数一样,得到如下结果:
mtcarsSpread <- mtcarsNew %>% spread(attribute, value)
head(mtcarsSpread)
car carb mpg cyl disp hp drat wt qsec vs am gear
1 AMC Javelin 2 15.2 8 304 150 3.15 3.435 17.30 0 0 3
2 Cadillac Fleetwood 4 10.4 8 472 205 2.93 5.250 17.98 0 0 3
3 Camaro Z28 4 13.3 8 350 245 3.73 3.840 15.41 0 0 3
4 Chrysler Imperial 4 14.7 8 440 230 3.23 5.345 17.42 0 0 3
5 Datsun 710 1 22.8 4 108 93 3.85 2.320 18.61 1 1 4
6 Dodge Challenger 2 15.5 8 318 150 2.76 3.520 16.87 0 0 3
unite
unite的调用格式如下:
unite(data, col, ..., sep = "_", remove = TRUE)
where ... represents the columns to unite and col represents the c
这里,...表示需要合并的列,col表示合并后的列。
我们先虚构一些数据:
set.seed(1)
date <- as.Date('2016-01-01') + 0:14
hour <- sample(1:24, 15)
min <- sample(1:60, 15)
second <- sample(1:60, 15)
event <- sample(letters, 15)
data <- data.frame(date, hour, min, second, event)
data
date hour min second event
1 2016-01-01 7 30 29 u
2 2016-01-02 9 43 36 a
3 2016-01-03 13 58 60 l
4 2016-01-04 20 22 11 q
5 2016-01-05 5 44 47 p
6 2016-01-06 18 52 37 k
7 2016-01-07 19 12 43 r
8 2016-01-08 12 35 6 i
9 2016-01-09 11 7 38 e
10 2016-01-10 1 14 21 b
11 2016-01-11 3 20 42 w
12 2016-01-12 14 1 32 t
13 2016-01-13 23 19 52 h
14 2016-01-14 21 41 26 s
15 2016-01-15 8 16 25 o
现在,我们需要把date,hour,min和second列合并为新列datetime。通常,R中的日期时间格式为"Year-Month-Day-Hour:Min:Second"。
dataNew <- data %>%
unite(datehour, date, hour, sep = ' ') %>%
unite(datetime, datehour, min, second, sep = ':')
dataNew
datetime event
1 2016-01-01 7:30:29 u
2 2016-01-02 9:43:36 a
3 2016-01-03 13:58:60 l
4 2016-01-04 20:22:11 q
5 2016-01-05 5:44:47 p
6 2016-01-06 18:52:37 k
7 2016-01-07 19:12:43 r
8 2016-01-08 12:35:6 i
9 2016-01-09 11:7:38 e
10 2016-01-10 1:14:21 b
11 2016-01-11 3:20:42 w
12 2016-01-12 14:1:32 t
13 2016-01-13 23:19:52 h
14 2016-01-14 21:41:26 s
15 2016-01-15 8:16:25 o
separate
separate的调用格式为:
separate(data, col, into, sep = "[^[:alnum:]]+", remove = TRUE,
convert = FALSE, extra = "warn", fill = "warn", ...)
我们可以用separate函数将数据恢复到刚创建的时候,如下所示:
data1 <- dataNew %>%
separate(datetime, c('date', 'time'), sep = ' ') %>%
separate(time, c('hour', 'min', 'second'), sep = ':')
data1
date hour min second event
1 2016-01-01 07 30 29 u
2 2016-01-02 09 43 36 a
3 2016-01-03 13 59 00 l
4 2016-01-04 20 22 11 q
5 2016-01-05 05 44 47 p
6 2016-01-06 18 52 37 k
7 2016-01-07 19 12 43 r
8 2016-01-08 12 35 06 i
9 2016-01-09 11 07 38 e
10 2016-01-10 01 14 21 b
11 2016-01-11 03 20 42 w
12 2016-01-12 14 01 32 t
13 2016-01-13 23 19 52 h
14 2016-01-14 21 41 26 s
15 2016-01-15 08 16 25 o
首先,将datetime分为date列和time列。然后,将time列分为hour,min,second列。
向量是 R 语言中最基本的数据类型,在 R 中没有单独的标量(例如 1 本质上是 c(1)) 。
R 中可以用 = 或者 <- 来进行赋值 , <-的快捷键是 alt + - 。
R的下标是从1开始的,和python等不同(python四从0开始的)
当然我们也可以用逻辑进行筛选,例如
负数下标表示不选这个这些下标,例如:
c() 可以合并向量,例如
向量有个比较有趣的性质,当两个向量进行操作时,如果长度不等, 长度比较短的一个会复制自己直到自己和长的一样长。
a 自动变成了 c(3,4,3,4) 然后与b相加 , 得到了下面的结果。
遇到不懂得函数,可以用help("函数")查看函数用法。
矩阵,从本质上来说就是多维的向量,我们来看一看 我们如何新建一个矩阵。
可以看到向量元素变为矩阵元素的方式是按列的,从第一列 到第二列,如果我们想按行输入元素,那么需要加入 byrow = TRUE 的参数:
与向量相似,我们可以用下标来筛选矩阵, 例如:
a[行,列]
当我们对两个矩阵相乘,我们得到的结果是 对应元素两两相乘的结果,例如:
而这不是我们想要的矩阵乘法,在 R 中我们在乘法旁边加两个 百分号来做矩阵乘法:
此外,我们可以用 t() 来求矩阵的转置 , 用 solve() 来求矩阵的逆。
数据框类似矩阵,与矩阵不同的是,数据框可以有不同的数据类型。 一般做数据分析,我们把一个类似 excel 的表格读入 R ,默认的格式 就是数据框 , 可见数据框是一个非常重要的数据结构。
一般来说我们需要分析的数据,每一行代表一个样本,每一列代表一个 变量。
下面我们用 R 内置的数据集 iris 来看一看数据框的使用。
我们用 data 函数调入了 iris 这个数据集 , 然后用 head 函数来看一看这个数据 的前几行 , 可以看到有 sepal 的长度,宽度,petal 的长度和宽度,还有一个变量 Species 来描述样本的类别。
我们可以用 summary 函数来对数据集做大致的了解。
可以直观地看到每个变量的信息,对于几个数值变量,我们可以看到最小值,中位数等等统计信息。而对于 Species 这个分类变量,我们看到的是计数信息。
筛选数据框与矩阵相似,都可以通过数字下标来获取子集,不同地是因为数据框有不同的列名,我们也可以通过列名来获取某一特定列,例如:
我们可以用 names() 函数来获取数据框的列名
并可以通过为其赋值改变列的名字。
列表是一种递归式的向量,我们可以用列表来存储不同类型的数据,比如:
列表有多种索引方式,可以用如下方式获取。
今天我们实验的对象就是一组从原始 R 进化出来的工具链 Tidyverse , 它是由 Hadley Wickham 主导开发的一系列 R 包的集合。 Tidyverse 继承了R语言进行快速统计分析的优势 , 并实现了一些新的理念 , 例如 magrittr 包中的管道操作 , 让线性嵌套的函数组合变得更加清晰易懂;可视化方面中的 ggplot ,使绘图变成搭积木式的图层叠加。
这样的小发明有的改变了分析的运作方式 , 有的改变了使用者的认知方式 , 聚在一起形成了一种新的数据分析的生态链 。具体来看 , Tidyverse 有如下核心组件:
mpg 数据集是刻画不同汽车的排放状况的一个数据集, 总过有 234 个样本 , 11 个变量 。 这 11 个变量分别是:
manufacture: 制造商
model: 车型
dispel: 汽车排放量
year: 制造年度
cyl: 排气管数量
trans: 排放类型
drv: 驱动方式
cty: 每公里耗油量(城市道路)
hwy: 每公里耗油量(高速路)
fl: 油的种类
class: 车的类型
更多数据相关信息可以通过 help(mpg) 指令获取。
在属性映射中加入 color=class 参数后 , 我们可以看到每个点的汽车对应的类型被用 不同颜色表现了出来 , 对于散点图 , 还有 size(大小) , shape(形状) 等等参数 可以用于确定点的属性。
对于条形图的y轴就是数据框中原本的数值时,必须将geom_bar()函数中stat(统计转换)参数设置为’identity’,即对原始数据集不作任何统计变换,而该参数的默认值为’count’,即观测数量。
r代码默认的颜色改回来使用scales包。R语言ggplot中的颜色ggplot2分组时默认使用的颜色,可以从另一个hadley写的包,进入scales包中有调用改变颜色。这个包算是一个工具包,用于和hadley写的其他包配合使用,颜色是其中一部分。