R语言机器学习入门——07

257 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 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)