第五章:数据操作Ⅱ 第二节:数据分析:拆分、应用、合并

我们可以使用plyr()来对数据进行拆分、应用和合并,plyr()的输入可以是数组、数据框、列表,输出也可以是数组、数据框、列表,还可以不输出任何结果,因此可以极大的减少数据转换的负担。

Plyr包中,数据处理函数的名称由5个字符组成,格式为{adl}{adl_}ply。第一个字符根据输入数据的类型,可以时a{数组}、d{数据框}、l{列表};第二个字符表示输出的类型,与上述一致,不过可以有无输出“_”

我们先安装plyr函数

install.packages("plyr")

library(plyr)

一、adply()函数

Adply()函数用于接收数组输入和返回数据框(d),但是其并不要求输入的数据完全是数组,其主要是是否能被数字索引读取,及主要是否为“矩阵”形式的数据,因此其也可以接受数据框的输入

在之前的apply()函数系列函数中提到,apply()函数在进行行处理时,如果各列有不同的数据类型,则会发生数据转换,导致输出的数据类型出错,而使用adply()函数时就可以避免这种情况发生

> apply(iris,1,function(row){print(row)})
Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species
       "5.1"        "3.5"        "1.4"        "0.2"     "setosa"
Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species
       "4.9"        "3.0"        "1.4"        "0.2"     "setosa"
Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species
       "4.7"        "3.2"        "1.3"        "0.2"     "setosa"
Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species

例如我们用函数查看数据框的每行,并且判断当前行的Sepal.Length是否大于0.5

> adply(iris,1,function(row){row$Sepal.Length>=5.0&row$Species=="setosa"})
    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species    V1
1            5.1         3.5          1.4         0.2     setosa  TRUE
2            4.9         3.0          1.4         0.2     setosa FALSE
3            4.7         3.2          1.3         0.2     setosa FALSE
4            4.6         3.1          1.5         0.2     setosa FALSE

当然,我们可以尝试适当指定保存新数据的列名

> adply(iris,1,function(row){data.frame(sepal_ge_5_setosa=c(row$Sepal.Length>=5.0&row$Species=="setosa"))})
#这个函数接受每行数据作为row参数,然后使用data.frame()函数创建一个新的数据框,其中包含一个名为
#sepal_ge_5_setosa的列,记录了对Sepal.Length是否大于等于5.0且Species是否为"setosa"的条件判断结果


    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species sepal_ge_5_setosa
1            5.1         3.5          1.4         0.2     setosa              TRUE
2            4.9         3.0          1.4         0.2     setosa             FALSE
3            4.7         3.2          1.3         0.2     setosa             FALSE
4            4.6         3.1          1.5         0.2     setosa             FALSE
5            5.0         3.6          1.4         0.2     setosa              TRUE
6            5.4         3.9          1.7         0.4     setosa              TRUE

二、ddply()函数

Ddply()函数接受数据框的输入,接受数据框

根adply不同的是,ddply()是根据.(variables)列出的列拆分数据,然后应用指定函数。

例如,我们从鸢尾花数据集中依据Species分别计算Sepal.Length的平均值

> ddply(iris,.(Species),function(sub){data.frame(Sepal.width.mean=mean(sub$Sepal.Width))})
     Species Sepal.width.mean
1     setosa            3.428
2 versicolor            2.770
3  virginica            2.974

如果需要针对多个变量对数据分组,只要在.()中罗列多个条件或列名即可,同时让这些条件和列名用逗号分割

例如,我们用鸢尾花品种和Sepal.Length是否大于5来做判断条件,然后计算每个分组的Sepal.Width平均值

> ddply(iris,.(Species,Sepal.Length>=5),function(sub){data.frame(Sepal.width.mean=mean(sub$Sepal.Width))})
     Species Sepal.Length >= 5 Sepal.width.mean
1     setosa             FALSE         3.140000
2     setosa              TRUE         3.620000
3 versicolor             FALSE         2.400000
4 versicolor              TRUE         2.777551
5  virginica             FALSE         2.500000
6  virginica              TRUE         2.983673

三、轻松进行按组运算

在常用类型计算中,我们可以使用transform()、mutate()、summarise()函数,让计算更容易

(一)transform

我们在这里使用美国职业棒球选手数据(baseball)数据进行演示。

> head(baseball)
           id year stint team lg  g  ab  r  h X2b X3b hr rbi sb cs bb so ibb hbp sh sf
4   ansonca01 1871     1  RC1    25 120 29 39  11   3  0  16  6  2  2  1  NA  NA NA NA
44  forceda01 1871     1  WS3    32 162 45 45   9   4  0  29  8  0  4  0  NA  NA NA NA
68  mathebo01 1871     1  FW1    19  89 15 24   3   1  0  10  2  1  2  0  NA  NA NA NA
99  startjo01 1871     1  NY2    33 161 35 58   5   1  1  34  4  2  3  0  NA  NA NA NA
102 suttoez01 1871     1  CL1    29 128 35 45   3   7  3  23  3  1  1  0  NA  NA NA NA
106 whitede01 1871     1  CL1    29 146 40 47   6   5  1  21  2  2  4  1  NA  NA NA NA

我们以选手ID为分组依据,计算每个分组中当前值与当前分组中最小值之差,保存到cyear

> head(ddply(baseball,.(id),transform,cyear=year-min(year)+1))
         id year stint team lg   g  ab   r   h X2b X3b hr rbi sb cs bb so ibb hbp sh sf
1 aaronha01 1954     1  ML1 NL 122 468  58 131  27   6 13  69  2  2 28 39  NA   3  6  4
2 aaronha01 1955     1  ML1 NL 153 602 105 189  37   9 27 106  3  1 49 61   5   3  7  4
3 aaronha01 1956     1  ML1 NL 153 609 106 200  34  14 26  92  2  4 37 54   6   2  5  7
4 aaronha01 1957     1  ML1 NL 151 615 118 198  27   6 44 132  1  1 57 58  15   0  0  3
5 aaronha01 1958     1  ML1 NL 153 601 109 196  34   4 30  95  4  1 59 49  16   1  0  3
6 aaronha01 1959     1  ML1 NL 154 629 116 223  46   7 39 123  8  0 51 54  17   4  0  9
  gidp cyear
1   13     1
2   20     2
3   21     3
4   13     4
5   21     5
6   19     6

(二)mutate()函数

使用mutate()函数向数据框中添加多个列时,后面添加的列可以直接引用前面添加的列

例如,我们可以在上述数据框下,生成一个log_cyear

> head(ddply(baseball,.(id),mutate,cyear=year-min(year)+1,log_year=log(cyear)))
         id year stint team lg   g  ab   r   h X2b X3b hr rbi sb cs bb so ibb hbp sh sf
1 aaronha01 1954     1  ML1 NL 122 468  58 131  27   6 13  69  2  2 28 39  NA   3  6  4
2 aaronha01 1955     1  ML1 NL 153 602 105 189  37   9 27 106  3  1 49 61   5   3  7  4
3 aaronha01 1956     1  ML1 NL 153 609 106 200  34  14 26  92  2  4 37 54   6   2  5  7
4 aaronha01 1957     1  ML1 NL 151 615 118 198  27   6 44 132  1  1 57 58  15   0  0  3
5 aaronha01 1958     1  ML1 NL 153 601 109 196  34   4 30  95  4  1 59 49  16   1  0  3
6 aaronha01 1959     1  ML1 NL 154 629 116 223  46   7 39 123  8  0 51 54  17   4  0  9
  gidp cyear  log_year
1   13     1 0.0000000
2   20     2 0.6931472
3   21     3 1.0986123
4   13     4 1.3862944
5   21     5 1.6094379
6   19     6 1.7917595

(三)summarise()函数

Summarise()函数会返回只包含计算结果的新数据框。例如:我们用summerise()函数进行汇总每个组里年份最小的数据

> head(ddply(baseball,.(id),summarise,min_year=min(year)))
         id min_year
1 aaronha01     1954
2 abernte02     1955
3 adairje01     1958
4 adamsba01     1906
5 adamsbo03     1946
6 adcocjo01     1950

如果我们求多个汇总值,则要罗列多个计算汇总值的表达式

> head(ddply(baseball,.(id),summarise,min_year=min(year),max_year=max(year)))
         id min_year max_year
1 aaronha01     1954     1976
2 abernte02     1955     1972
3 adairje01     1958     1970
4 adamsba01     1906     1926
5 adamsbo03     1946     1959
6 adcocjo01     1950     1966

(四)subset()函数

从整个数据集中获取符合条件的子集,只要满足条件就可以抽取

例如,我们抽取各个选手参数最多的一年所在的行

head(ddply(baseball,.(id),subset,g=max(g)))
         id year stint team lg   g  ab   r   h X2b X3b hr rbi sb cs bb so ibb hbp sh sf
1 aaronha01 1954     1  ML1 NL 122 468  58 131  27   6 13  69  2  2 28 39  NA   3  6  4
2 aaronha01 1955     1  ML1 NL 153 602 105 189  37   9 27 106  3  1 49 61   5   3  7  4
3 aaronha01 1956     1  ML1 NL 153 609 106 200  34  14 26  92  2  4 37 54   6   2  5  7
4 aaronha01 1957     1  ML1 NL 151 615 118 198  27   6 44 132  1  1 57 58  15   0  0  3
5 aaronha01 1958     1  ML1 NL 153 601 109 196  34   4 30  95  4  1 59 49  16   1  0  3
6 aaronha01 1959     1  ML1 NL 154 629 116 223  46   7 39 123  8  0 51 54  17   4  0  9
  gidp
1   13
2   20
3   21
4   13
5   21
6   19

三、mdply()

Mdply()可以接受数据框数组,将指定行数应用到各列,然后合并执行结果

例如,我们利用mdply()函数来传递生成正态分布随机数

> (x<-data.frame(mean=1:5,sd=1:5))
  mean sd
1    1  1
2    2  2
3    3  3
4    4  4
5    5  5
> mdply(x,rnorm,n=2)
  mean sd         V1         V2
1    1  1  3.3823125  0.7413170
2    2  2  0.3226491  3.9972046
3    3  3 -1.1046600  0.1680206
4    4  4  0.6956026  6.4022236
5    5  5 -1.0052694 11.9224206

  • 25
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值