开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情
数据转换(六)——tidyr包的使用
Tidyr数据是一种很简洁的数据,数据的每一列代表一个变量,每一行代表一个观测,每一个观测的值在表中为一个单元格,也就是一个观测一个变量确定唯一的一个值。
接下来使用mtcars的数据来介绍一下tidyr包的函数用法
Mtcars数据是很典型的一个tidyr数据,先取数据的10行和3列,赋值到一个新的变量上。
tdata <- mtcars[1:10,1:3]
取数据的行名生成新的一个数据框(方便处理)
tdata <- data.frame(names=rownames(tdata),tdata)
gather函数:
gather(data,key,value…..),data参数是要处理的数据,key参数是宽数据变为长数据时,存放需要编码的变量的变量名称,需要自己定义,value参数是需要数据转换的变量的数值,也需要自己定义。
gather(tdata,kkey = 'key',value = 'value',cyl,disp,mpg)
处理前数据:
names 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
处理后数据:
names key value
1 Mazda RX4 cyl 6.0
2 Mazda RX4 Wag cyl 6.0
3 Datsun 710 cyl 4.0
4 Hornet 4 Drive cyl 6.0
5 Hornet Sportabout cyl 8.0
6 Valiant cyl 6.0
7 Duster 360 cyl 8.0
8 Merc 240D cyl 4.0
9 Merc 230 cyl 4.0
10 Merc 280 cyl 6.0
11 Mazda RX4 disp 160.0
可以使用冒号,制定多列聚到同一列中,此处是将cyl与mpg先合并,然后在和disp组成一个数据框
gather(tdata,key = 'key',value = 'value',cyl:mpg,disp)
如果该在列名称前添加一个负号,代表不需要转换该列
也可以直接使用列的索引编号进行数据的重新构造
gather(tdata,key = 'key',value = 'value',2:4)
Spread函数则是将合并数据转化成tidyr形式的数据
例如,对之前合并的tdata函数进行分开:
gdata <- gather(tdata,key='key',value = 'value',2:4)
spread(gdata,key = 'key',value="value")
就可以还原数据:
Separate函数可以把一列拆成多个列:
例如我们创建一个数据框df
df <- data.frame(x=c(NA,"a.b","a.d","b.c"))
将数据按照“.”分成两列:
separate(df,col = x,into = c('A','B'))
对x这列进行分割,分割成A、B两列,默认识别分隔符
分割之前:
分割之后:
当出现多个分隔符而识别出现错误时,例如以下情况:
df <- data.frame(x=c(NA,"a.b-c","a-d","b-c"))
则可以利用sep函数指定分隔符,这样就能顺利分列:
separate(df,col = x,into = c('A','B'),sep="-")
可以使用unite函数将分开的列连接起来
unite(x,col ="AB",A,B,sep = "-")
x是需要处理的数据,col是连接后字段的名字,A,B是需要连接的字段,sep是用于连接的连接符
连接之后:
数据处理——dplyr包的使用
使用iris数据对dplyr包的用法做介绍,首先是filter函数
可以使用filter函数用指定条件对数据进行筛选,比如以下代码可以筛选掉花萼长度在7以下的数据,保留在7以上的数据
dplyr::filter(iris,Sepal.Length>7)
distinct函数可以用于去除重复行,相当于unique函数的功能
比如,可以使用rbind函数合并iris数据集的1-10行数据与1-15行数据,再使用第三条函数去除多余行:
dplyr::distinct(rbind(iris[1:10,],iris[1:15,]))
以上代码的运行结果只会保留,10-15行的数据,因为1-10行数据是重复的
Slice函数可以用于切片,可以取出数据的任意行:
dplyr::slice(iris,10:15)
以上代码可以取出iris数据的10-15行
Sample_n函数用于随机取样,例如:
dplyr::sample_n(iris,10)
代表在iris这个数据中随机抽取10行
Sample_frac表示按比例随机选取,比如抽取源数据的10%的数据,是指百分比:
dplyr::sample_frac(iris,0.1)
arrange函数用于排序,比如将iris数据按照花萼长度进行排序(正向),可写成:
dplyr::arrange(iris,Sepal.Length)
如果加上前面加上负号则是进行反向排序(从大到小)
dplyr::arrange(iris,-Sepal.Length)
关于dplyr的统计函数:
可以使用summarise()函数进行统计,比如统计花萼长度的平均值:
summarise(iris,avg=mean(Sepal.Length))
统计花萼长度的和:
summarise(iris,total=sum(Sepal.Length))
R中一个非常有用的负号:%>% 这个符号是链式操作符,它的功能是用于实现将一个函数的输出传递给下一个函数,作为下一个函数的输入,在键盘上可以用Ctrl+shift+M的快捷键打出来,有点类似于“且”的概念。
比如,先使用head函数取出数据集的前20行,再使用链式操作符,可以将这20行数据作为下一个命令的输入,如下一个命令是tail(10),也就是取出倒数10行,那么就会取出这20行数据的第11-20行:
head(mtcars,20)
head(mtcars,20) %>% tail(10)
Group_by函数可以对数据进行分组,例如根据species这列对数据进行分组:
如果用链式操作符,代码可以改为:
iris %>% group_by(Species)
还可以结合summarize统计函数进行进一步的计算,例如可以计算每一种类型鸢尾花品种的花萼宽度的平均值:
iris %>% group_by(Species) %>% summarise(avg=mean(Sepal.Width))
在此基础上,还可以使用链式操作符,对宽度的平均值进行排序:
iris %>% group_by(Species) %>% summarise(avg=mean(Sepal.Width)) %>% arrange(avg)
mutate函数可以添加新的变量
使用mutate函数在iris数据中增加一行,该行数据是花萼与花瓣长度的总和:
dplyr::mutate(iris,new=Sepal.Length+Petal.Length)
下面介绍一下的dplyr包对于双表格的操作:
比如将两个表格整合到一起,先创建两个数据框,分别是a,b
a=data.frame(x1=c('A','B','C'),x2=c(1,2,3))
b=data.frame(x1=c('A','B','D'),x2=c(T,F,T))
首先是左连接,left_join(),以x1列为基础进行连接
dplyr::left_join(a,b,by="x1")
然后是右连接,right_join(),是以b的x1列为基础进行连接,
然后是内连接和全连接,内连接是取x1的交集,全连接是取x1的并集
内连接:
dplyr::inner_join(a,b,by="x1")
全连接:
dplyr::full_join(a,b,by="x1")
半连接相当于根据右侧表的内容对左侧表进行过滤,也就是将两个表的数据的交集取出来:
半连接:
dplyr::semi_join(a,b,by="x1")
反连接是输出两个表的补集部分,也就是取出数据框a中b不含有的行:
dplyr::anti_join(a,b,by="x1")
以上两个函数是互补的函数,一个是取共有的,一个是取没有的。
下面来看几个数据框的合并操作
首先定义数据first变量,变量取mtcars数据前20行,second变量取第10-30行,由于slice函数取出的数据不含行名,需要在取出数据前用mutate函数添加一列行名
mtcars <- mutate(mtcars,names=row.names(mtcars))
first <- slice(mtcars,1:20)
second <- slice(mtcars,10:30)
然后验证函数
Intersect()取交集:
> intersect(first,second)
Union_all()取并集:
dplyr::union_all(first,second)
Union()取非冗余的并集,去除掉重复部分再进行合并:
dplyr::union(first,second)
setdiff()取数据的补集,也就是取出frist数据中second数据没有的部分:
setdiff(first,second)