R语言小白学习笔记7—高效的分组操作:dplyr

笔记链接

学习笔记1—R语言基础.
学习笔记2—高级数据结构.
学习笔记3—R语言读取数据.
学习笔记4—统计图.
学习笔记5—编写R语言函数和简单的控制循环语句.
学习笔记6—分组操作.

学习笔记7—高效的分组操作:dplyr

dplyr包中的d代表着数据框,其处理速度更快

同时使用plyr和dplyr包时,要先加载plyr包,再加载dplyr包,因为其包中含有很多函数具有相同函数名,而后加载的包会有高优先级。

7.1 管道和tbl数据类型

dplyr包不仅处理速度快,而且可以使用magrittr包的管道流程。(管道语法见笔记:R语言基础)

例:将diamonds数据先传入head函数,再将结果传入dim函数(行数列数)

> library(magrittr)
> data(diamonds, package = "ggplot2")
> dim(head(diamonds, n=4))
[1]  4 10
> diamonds %>% head(4) %>% dim
[1]  4 10

tbl特点是当打印数据集时,默认只有一部分行数据会显示,列数据会适应屏幕大小显示。另一个特点是列名下面会显示每行的数据类型

最新版本的ggplot2包的diamonds数据集存储为tbl_df(tbl对象的扩展)类型。

> class(diamonds)
[1] "tbl_df"     "tbl"        "data.frame"
> head(diamonds)
  carat       cut color clarity depth table price    x
1  0.23     Ideal     E     SI2  61.5    55   326 3.95
2  0.21   Premium     E     SI1  59.8    61   326 3.89
3  0.23      Good     E     VS1  56.9    65   327 4.05
4  0.29   Premium     I     VS2  62.4    58   334 4.20
5  0.31      Good     J     SI2  63.3    58   335 4.34
6  0.24 Very Good     J    VVS2  62.8    57   336 3.94
     y    z
1 3.98 2.43
2 3.84 2.31
3 4.07 2.31
4 4.23 2.63
5 4.35 2.75
6 3.96 2.48

加载dplyr包后,diamonds数据集将以tbl对象打印

因为tbl对象的打印只会显示部分行数据,所以不需要使用head函数:

> library(dplyr)
> diamonds
# A tibble: 53,940 x 10
   carat cut   color clarity depth table price     x
   <dbl> <ord> <ord> <ord>   <dbl> <dbl> <int> <dbl>
 1 0.23  Ideal E     SI2      61.5    55   326  3.95
 2 0.21  Prem~ E     SI1      59.8    61   326  3.89
 3 0.23  Good  E     VS1      56.9    65   327  4.05
 4 0.290 Prem~ I     VS2      62.4    58   334  4.2 
 5 0.31  Good  J     SI2      63.3    58   335  4.34
 6 0.24  Very~ J     VVS2     62.8    57   336  3.94
 7 0.24  Very~ I     VVS1     62.3    57   336  3.95
 8 0.26  Very~ H     SI1      61.9    55   337  4.07
 9 0.22  Fair  E     VS2      65.1    61   337  3.87
10 0.23  Very~ H     VS1      59.4    61   338  4   
# ... with 53,930 more rows, and 2 more variables:
#   y <dbl>, z <dbl>

7.2 select函数

功能:选择列数据

select函数第一个参数为数据框或tbl对象,后面的参数为待操作的列。

> select(diamonds, carat, price)
# A tibble: 53,940 x 2
   carat price
   <dbl> <int>
 1 0.23    326
 2 0.21    326
 3 0.23    327
 4 0.290   334
 5 0.31    335
 6 0.24    336
 7 0.24    336
 8 0.26    337
 9 0.22    337
10 0.23    338
# ... with 53,930 more rows

列名也可以以向量传入。(书上讲了一部分select_函数内容,但我输入后显示这种方法已经废弃)

如果列名是以变量的形式存储,则需要使用one_of函数:

> theCols <- c('carat', 'price')
> diamonds %>% select(one_of(theCols))
# A tibble: 53,940 x 2
   carat price
   <dbl> <int>
 1 0.23    326
 2 0.21    326
 3 0.23    327
 4 0.290   334
 5 0.31    335
 6 0.24    336
 7 0.24    336
 8 0.26    337
 9 0.22    337
10 0.23    338
# ... with 53,930 more rows

使用中括号语法,列名就可以用位置索引来指定:

> select(diamonds, 1, 7)
# A tibble: 53,940 x 2
   carat price
   <dbl> <int>
 1 0.23    326
 2 0.21    326
 3 0.23    327
 4 0.290   334
 5 0.31    335
 6 0.24    336
 7 0.24    336
 8 0.26    337
 9 0.22    337
10 0.23    338
# ... with 53,930 more rows

dplyr包的starts_with、ends_with和contains函数可以进行部分搜索

> diamonds %>% select(starts_with('c'))
# A tibble: 53,940 x 4
   carat cut       color clarity
   <dbl> <ord>     <ord> <ord>  
 1 0.23  Ideal     E     SI2    
 2 0.21  Premium   E     SI1    
 3 0.23  Good      E     VS1    
 4 0.290 Premium   I     VS2    
 5 0.31  Good      J     SI2    
 6 0.24  Very Good J     VVS2   
 7 0.24  Very Good I     VVS1   
 8 0.26  Very Good H     SI1    
 9 0.22  Fair      E     VS2    
10 0.23  Very Good H     VS1    
# ... with 53,930 more rows

select使用减号(-)来排除列数据

> diamonds %>% select(-carat, -price)
# A tibble: 53,940 x 8
   cut       color clarity depth table     x     y     z
   <ord>     <ord> <ord>   <dbl> <dbl> <dbl> <dbl> <dbl>
 1 Ideal     E     SI2      61.5    55  3.95  3.98  2.43
 2 Premium   E     SI1      59.8    61  3.89  3.84  2.31
 3 Good      E     VS1      56.9    65  4.05  4.07  2.31
 4 Premium   I     VS2      62.4    58  4.2   4.23  2.63
 5 Good      J     SI2      63.3    58  4.34  4.35  2.75
 6 Very Good J     VVS2     62.8    57  3.94  3.96  2.48
 7 Very Good I     VVS1     62.3    57  3.95  3.98  2.47
 8 Very Good H     SI1      61.9    55  4.07  4.11  2.53
 9 Fair      E     VS2      65.1    61  3.87  3.78  2.49
10 Very Good H     VS1      59.4    61  4     4.05  2.39
# ... with 53,930 more rows

当使用one_of函数时,减号必须在one_of之前

> diamonds %>% select(-one_of('carat', 'price'))
# A tibble: 53,940 x 8
   cut       color clarity depth table     x     y     z
   <ord>     <ord> <ord>   <dbl> <dbl> <dbl> <dbl> <dbl>
 1 Ideal     E     SI2      61.5    55  3.95  3.98  2.43
 2 Premium   E     SI1      59.8    61  3.89  3.84  2.31
 3 Good      E     VS1      56.9    65  4.05  4.07  2.31
 4 Premium   I     VS2      62.4    58  4.2   4.23  2.63
 5 Good      J     SI2      63.3    58  4.34  4.35  2.75
 6 Very Good J     VVS2     62.8    57  3.94  3.96  2.48
 7 Very Good I     VVS1     62.3    57  3.95  3.98  2.47
 8 Very Good H     SI1      61.9    55  4.07  4.11  2.53
 9 Fair      E     VS2      65.1    61  3.87  3.78  2.49
10 Very Good H     VS1      59.4    61  4     4.05  2.39
# ... with 53,930 more rows

7.3 filter函数

filter函数通过逻辑表达式指定行数据。

> diamonds %>% filter(cut == 'Ideal')
# A tibble: 21,551 x 10
   carat cut   color clarity depth table price     x
   <dbl> <ord> <ord> <ord>   <dbl> <dbl> <int> <dbl>
 1  0.23 Ideal E     SI2      61.5    55   326  3.95
 2  0.23 Ideal J     VS1      62.8    56   340  3.93
 3  0.31 Ideal J     SI2      62.2    54   344  4.35
 4  0.3  Ideal I     SI2      62      54   348  4.31
 5  0.33 Ideal I     SI2      61.8    55   403  4.49
 6  0.33 Ideal I     SI2      61.2    56   403  4.49
 7  0.33 Ideal J     SI1      61.1    56   403  4.49
 8  0.23 Ideal G     VS1      61.9    54   404  3.93
 9  0.32 Ideal I     SI1      60.9    55   404  4.45
10  0.3  Ideal I     SI2      61      59   405  4.3 
# ... with 21,541 more rows, and 2 more variables:
#   y <dbl>, z <dbl>

filter函数可以使用操作符(%in%)来选择许多可能值中的一个

> diamonds %>% filter(cut %in% c('Ideal', 'Good'))
# A tibble: 26,457 x 10
   carat cut   color clarity depth table price     x
   <dbl> <ord> <ord> <ord>   <dbl> <dbl> <int> <dbl>
 1  0.23 Ideal E     SI2      61.5    55   326  3.95
 2  0.23 Good  E     VS1      56.9    65   327  4.05
 3  0.31 Good  J     SI2      63.3    58   335  4.34
 4  0.3  Good  J     SI1      64      55   339  4.25
 5  0.23 Ideal J     VS1      62.8    56   340  3.93
 6  0.31 Ideal J     SI2      62.2    54   344  4.35
 7  0.3  Ideal I     SI2      62      54   348  4.31
 8  0.3  Good  J     SI1      63.4    54   351  4.23
 9  0.3  Good  J     SI1      63.8    56   351  4.23
10  0.3  Good  I     SI2      63.3    56   351  4.26
# ... with 26,447 more rows, and 2 more variables:
#   y <dbl>, z <dbl>

可以用逗号(,)或者与符号(&)连接进行组合过滤

> diamonds %>% filter(carat > 2, price < 14000)
# A tibble: 644 x 10
   carat cut   color clarity depth table price     x
   <dbl> <ord> <ord> <ord>   <dbl> <dbl> <int> <dbl>
 1  2.06 Prem~ J     I1       61.2    58  5203  8.1 
 2  2.14 Fair  J     I1       69.4    57  5405  7.74
 3  2.15 Fair  J     I1       65.5    57  5430  8.01
 4  2.22 Fair  J     I1       66.7    56  5607  8.04
 5  2.01 Fair  I     I1       67.4    58  5696  7.71
 6  2.01 Fair  I     I1       55.9    64  5696  8.48
 7  2.27 Fair  J     I1       67.6    55  5733  8.05
 8  2.03 Fair  H     I1       64.4    59  6002  7.91
 9  2.03 Fair  H     I1       66.6    57  6002  7.81
10  2.06 Good  H     I1       64.3    58  6091  8.03
# ... with 634 more rows, and 2 more variables: y <dbl>,
#   z <dbl>

7.4 slice函数

slice函数通过行数字指定行数据

需要把想要的索引作为一个向量传入slice函数。
(slice翻译:把…切成(薄)片;切;割)

> diamonds %>% slice(c(1:5, 8, 15:20))
# A tibble: 12 x 10
   carat cut   color clarity depth table price     x
   <dbl> <ord> <ord> <ord>   <dbl> <dbl> <int> <dbl>
 1 0.23  Ideal E     SI2      61.5    55   326  3.95
 2 0.21  Prem~ E     SI1      59.8    61   326  3.89
 3 0.23  Good  E     VS1      56.9    65   327  4.05
 4 0.290 Prem~ I     VS2      62.4    58   334  4.2 
 5 0.31  Good  J     SI2      63.3    58   335  4.34
 6 0.26  Very~ H     SI1      61.9    55   337  4.07
 7 0.2   Prem~ E     SI2      60.2    62   345  3.79
 8 0.32  Prem~ E     I1       60.9    58   345  4.38
 9 0.3   Ideal I     SI2      62      54   348  4.31
10 0.3   Good  J     SI1      63.4    54   351  4.23
11 0.3   Good  J     SI1      63.8    56   351  4.23
12 0.3   Very~ J     SI1      62.7    59   351  4.21
# ... with 2 more variables: y <dbl>, z <dbl>

注意:打印的行数不是函数中行数字,只是返回结果。

负索引可以显示上边没返回的行:

> diamonds %>% slice(-1)
# A tibble: 53,939 x 10
   carat cut   color clarity depth table price     x
   <dbl> <ord> <ord> <ord>   <dbl> <dbl> <int> <dbl>
 1 0.21  Prem~ E     SI1      59.8    61   326  3.89
 2 0.23  Good  E     VS1      56.9    65   327  4.05
 3 0.290 Prem~ I     VS2      62.4    58   334  4.2 
 4 0.31  Good  J     SI2      63.3    58   335  4.34
 5 0.24  Very~ J     VVS2     62.8    57   336  3.94
 6 0.24  Very~ I     VVS1     62.3    57   336  3.95
 7 0.26  Very~ H     SI1      61.9    55   337  4.07
 8 0.22  Fair  E     VS2      65.1    61   337  3.87
 9 0.23  Very~ H     VS1      59.4    61   338  4   
10 0.3   Good  J     SI1      64      55   339  4.25
# ... with 53,929 more rows, and 2 more variables:
#   y <dbl>, z <dbl>

7.5 mutate函数

mutate函数能增加新列或修改已经存在的列。
(mutate翻译:转变;转换)

例:通过两变量的比值增加新列并分配列名

这里用select函数原因是输出尺寸不同可能显示不出来

> diamonds %>% select(carat, price) %>% mutate(Ratio=price/carat)
# A tibble: 53,940 x 3
   carat price Ratio
   <dbl> <int> <dbl>
 1 0.23    326 1417.
 2 0.21    326 1552.
 3 0.23    327 1422.
 4 0.290   334 1152.
 5 0.31    335 1081.
 6 0.24    336 1400 
 7 0.24    336 1400 
 8 0.26    337 1296.
 9 0.22    337 1532.
10 0.23    338 1470.
# ... with 53,930 more rows

注意:这时并没有改变原始数据集

若想要保存结果,可以用分配符(%<>%)将左边的对象传给右边的函数,并将返回的结果分配给左边的对象:

> diamonds2 <- diamonds
> diamonds2
# A tibble: 53,940 x 10
   carat cut   color clarity depth table price     x
   <dbl> <ord> <ord> <ord>   <dbl> <dbl> <int> <dbl>
 1 0.23  Ideal E     SI2      61.5    55   326  3.95
 2 0.21  Prem~ E     SI1      59.8    61   326  3.89
 3 0.23  Good  E     VS1      56.9    65   327  4.05
 4 0.290 Prem~ I     VS2      62.4    58   334  4.2 
 5 0.31  Good  J     SI2      63.3    58   335  4.34
 6 0.24  Very~ J     VVS2     62.8    57   336  3.94
 7 0.24  Very~ I     VVS1     62.3    57   336  3.95
 8 0.26  Very~ H     SI1      61.9    55   337  4.07
 9 0.22  Fair  E     VS2      65.1    61   337  3.87
10 0.23  Very~ H     VS1      59.4    61   338  4   
# ... with 53,930 more rows, and 2 more variables:
#   y <dbl>, z <dbl>
> diamonds2 %<>% select(carat, price) %>% 
+     mutate(Ratio=price/carat, Double=Ratio*2)
> diamonds2
# A tibble: 53,940 x 4
   carat price Ratio Double
   <dbl> <int> <dbl>  <dbl>
 1 0.23    326 1417.  2835.
 2 0.21    326 1552.  3105.
 3 0.23    327 1422.  2843.
 4 0.290   334 1152.  2303.
 5 0.31    335 1081.  2161.
 6 0.24    336 1400   2800 
 7 0.24    336 1400   2800 
 8 0.26    337 1296.  2592.
 9 0.22    337 1532.  3064.
10 0.23    338 1470.  2939.
# ... with 53,930 more rows

7.6 summarize函数

summarize函数适用于返回结果长度为1的函数,比如mean、max、median等等。

例:计算数据集某列平均值

> diamonds %>% summarize(mean(price))
# A tibble: 1 x 1
  `mean(price)`
          <dbl>
1         3933.

summarize函数的一大特点是:可以对结果进行重命名,并且一次调用能完成多种计算

> diamonds %>% 
+     summarize(AvgPrice=mean(price),
+               MediamPrice=median(price),
+               AvgCarat=mean(carat))
# A tibble: 1 x 3
  AvgPrice MediamPrice AvgCarat
     <dbl>       <dbl>    <dbl>
1    3933.        2401    0.798

7.7 group_by函数

group_by函数能分组数据,并对部分数据单独应用函数。

例:根据某个变量分组,然后对每一部分数据应用summarize函数

> diamonds %>% 
+     group_by(cut) %>%
+     summarize(AvgPrice=mean(price))
# A tibble: 5 x 2
  cut       AvgPrice
* <ord>        <dbl>
1 Fair         4359.
2 Good         3929.
3 Very Good    3982.
4 Premium      4584.
5 Ideal        3458.

7.8 arrange函数

arrange函数可以进行排序,比R基础包中的order和sort函数更易理解

> diamonds %>% 
+     group_by(cut) %>%
+     summarize(AvgPrice=mean(price), SumCarat=sum(carat)) %>%
+     arrange(desc(AvgPrice))
# A tibble: 5 x 3
  cut       AvgPrice SumCarat
  <ord>        <dbl>    <dbl>
1 Premium      4584.   12301.
2 Fair         4359.    1684.
3 Very Good    3982.    9743.
4 Good         3929.    4166.
5 Ideal        3458.   15147.

7.9 do函数

对于dplyr中特定操作函数(如:summarize等)未覆盖的通用目的的计算,可以使用do函数,其可以在数据上应用任意函数

例:

#创建一个对diamonds数据进行排序并返回前N行的函数
> topN <- function(x, N=5)
+ {
+     x %>% arrange(desc(price)) %>% head(N)
+ }
#结合group_by和do函数返回按变量分组、price变量排序的前N行数据
> diamonds %>% group_by(cut) %>% do(topN(., N=3))
#因为管道左侧没有传入指定的位置,所以可以用.指定位置
# A tibble: 15 x 10
# Groups:   cut [5]
   carat cut   color clarity depth table price     x
   <dbl> <ord> <ord> <ord>   <dbl> <dbl> <int> <dbl>
 1  2.01 Fair  G     SI1      70.6    64 18574  7.43
 2  2.02 Fair  H     VS2      64.5    57 18565  8   
 3  4.5  Fair  J     I1       65.8    58 18531 10.2 
 4  2.8  Good  G     SI2      63.8    58 18788  8.9 
 5  2.07 Good  I     VS2      61.8    61 18707  8.12
 6  2.67 Good  F     SI2      63.8    58 18686  8.69
 7  2    Very~ G     SI1      63.5    56 18818  7.9 
 8  2    Very~ H     SI1      62.8    57 18803  7.95
 9  2.03 Very~ H     SI1      63      60 18781  8   
10  2.29 Prem~ I     VS2      60.8    60 18823  8.5 
11  2.29 Prem~ I     SI1      61.8    59 18797  8.52
12  2.04 Prem~ H     SI1      58.1    60 18795  8.37
13  1.51 Ideal G     IF       61.7    55 18806  7.37
14  2.07 Ideal G     SI2      62.5    55 18804  8.2 
15  2.15 Ideal G     SI2      62.6    54 18791  8.29
# ... with 2 more variables: y <dbl>, z <dbl>

这里返回的结果是数据框,如果do函数是有名字的参数,则返回结果会变

> diamonds %>% group_by(cut) %>% do(Top=(topN(., N=3)))
# A tibble: 5 x 2
# Rowwise: 
  cut       Top              
  <ord>     <list>           
1 Fair      <tibble [3 x 10]>
2 Good      <tibble [3 x 10]>
3 Very Good <tibble [3 x 10]>
4 Premium   <tibble [3 x 10]>
5 Ideal     <tibble [3 x 10]>
> topByCut <- diamonds %>% group_by(cut) %>% do(Top=(topN(., N=3)))
> class(topByCut)
[1] "rowwise_df" "tbl_df"     "tbl"        "data.frame"
> topByCut$Top[[1]]
# A tibble: 3 x 10
  carat cut   color clarity depth table price     x     y
  <dbl> <ord> <ord> <ord>   <dbl> <dbl> <int> <dbl> <dbl>
1  2.01 Fair  G     SI1      70.6    64 18574  7.43  6.64
2  2.02 Fair  H     VS2      64.5    57 18565  8     7.95
3  4.5  Fair  J     I1       65.8    58 18531 10.2  10.2 
# ... with 1 more variable: z <dbl>

7.10 dplyr使用数据库

dplyr可以使用数据库存储的数据。

这里拿SOLite数据库举例。

例:

#先下载数据库
> download.file("http://www.jaredlander.com/data/diamonds.db", destfile = "E:/B/R/diamonds.db", mode='wb')
#首先为SQLite数据库创建一个连接。
#这里用src_sqlite函数直接warning了,书上说是因为版本的问题,所以这里用DBI创建连接
> diaDBSource <- src_sqlite("E:/B/R/diamonds.db")
Warning message:
`src_sqlite()` is deprecated as of dplyr 1.0.0.
Please use `tbl()` directly with a database connection
This warning is displayed once every 8 hours.
Call `lifecycle::last_warnings()` to see where this warning was generated. 
> diaDBSource2 <- DBI::dbConnect(RSQLite::SQLite(), "E:/B/R/diamonds.db")
> diaDBSource2
<SQLiteConnection>
  Path: E:\B\R\diamonds.db
  Extensions: TRUE
#接下来我们需要指向某个数据表,这里指向diamonds表
> diaTab <- tbl(diaDBSource2, "diamonds")
> diaTab
# Source:   table<diamonds> [?? x 10]
# Database: sqlite 3.34.1 [E:\B\R\diamonds.db]
   carat cut   color clarity depth table price     x
   <dbl> <chr> <chr> <chr>   <dbl> <dbl> <int> <dbl>
 1 0.23  Ideal E     SI2      61.5    55   326  3.95
 2 0.21  Prem~ E     SI1      59.8    61   326  3.89
 3 0.23  Good  E     VS1      56.9    65   327  4.05
 4 0.290 Prem~ I     VS2      62.4    58   334  4.2 
 5 0.31  Good  J     SI2      63.3    58   335  4.34
 6 0.24  Very~ J     VVS2     62.8    57   336  3.94
 7 0.24  Very~ I     VVS1     62.3    57   336  3.95
 8 0.26  Very~ H     SI1      61.9    55   337  4.07
 9 0.22  Fair  E     VS2      65.1    61   337  3.87
10 0.23  Very~ H     VS1      59.4    61   338  4   
# ... with more rows, and 2 more variables: y <dbl>,
#   z <dbl>

小结

这几节主要介绍了各种包的各种函数,确实挺多的也记不住,还需要多用一用。最后我打算再把书中的所有函数做个表格总结一下,这样想用的时候可以时刻查询。

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值