R语言--高效操作数据框(dplyr包)(1)

数据框是R语言中的一个重要数据结构,在数据分析过程中,主要的数据对象就是数据框。R语言内置了data.frame类,dplyr包则加强了数据框的各种操作,语法与SQL类似,使数据框的处理变得灵活多变,处理速度得到很大提升。

本文针对在数据分析中数据框使用的各种常用场景,总结了dplyr包的使用方法。本文为该系列的第一篇。

环境&软件

  • win10 64bit
  • R 3.6.1

安装包

install.packages("dplyr")

管道操作符 %>%

管道操作符%>%,在dplyr中被大量使用,用来简化代码结构,减少中间变量,使代码更符合思维习惯。RStudio快捷键:Ctrl+Shift+m

library(dplyr)
# 查看数据前3行
head(iris,3) # 常规方式
##   Sepal.Length Sepal.Width Petal.Length Petal.Width
## 1          5.1         3.5          1.4         0.2
## 2          4.9         3.0          1.4         0.2
## 3          4.7         3.2          1.3         0.2
##   Species
## 1  setosa
## 2  setosa
## 3  setosa
iris %>% head(3) # 管道符方式
##   Sepal.Length Sepal.Width Petal.Length Petal.Width
## 1          5.1         3.5          1.4         0.2
## 2          4.9         3.0          1.4         0.2
## 3          4.7         3.2          1.3         0.2
##   Species
## 1  setosa
## 2  setosa
## 3  setosa

数据框 tibble

tibble是data.frame的简化版本,适用data.frame的所有语法,同时有更简单的数据框创建方式。

# 1.data.frame转为tibble
as_tibble(mtcars)
## # A tibble: 32 x 11
##      mpg   cyl  disp    hp  drat    wt  qsec    vs    am
##    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
##  1  21       6  160    110  3.9   2.62  16.5     0     1
##  2  21       6  160    110  3.9   2.88  17.0     0     1
##  3  22.8     4  108     93  3.85  2.32  18.6     1     1
##  4  21.4     6  258    110  3.08  3.22  19.4     1     0
##  5  18.7     8  360    175  3.15  3.44  17.0     0     0
##  6  18.1     6  225    105  2.76  3.46  20.2     1     0
##  7  14.3     8  360    245  3.21  3.57  15.8     0     0
##  8  24.4     4  147.    62  3.69  3.19  20       1     0
##  9  22.8     4  141.    95  3.92  3.15  22.9     1     0
## 10  19.2     6  168.   123  3.92  3.44  18.3     1     0
## # … with 22 more rows, and 2 more variables:
## #   gear <dbl>, carb <dbl>
# 2.构造tibble,引用列变量
tibble(x=1:4,y=x+1)
## # A tibble: 4 x 2
##       x     y
##   <int> <dbl>
## 1     1     2
## 2     2     3
## 3     3     4
## 4     4     5
# 3.构造tibble,不引用列变量(!!)
x <- 11:14 
tibble(x=1:4,y=!!x+1)
## # A tibble: 4 x 2
##       x     y
##   <int> <dbl>
## 1     1    12
## 2     2    13
## 3     3    14
## 4     4    15

列筛选 select

select函数用来对数据框的列进行选择筛选。

# 数据
tbl_df <- tibble(var1=1:4,var2=2:5,label=c("a","b","a","c"))

基本方法

选择列的基本方法。

# 引用选择列
tbl_df %>% select(var1,var2) 
## # A tibble: 4 x 2
##    var1  var2
##   <int> <int>
## 1     1     2
## 2     2     3
## 3     3     4
## 4     4     5
# 范围引用选择列
tbl_df %>% select(var1:var2)
## # A tibble: 4 x 2
##    var1  var2
##   <int> <int>
## 1     1     2
## 2     2     3
## 3     3     4
## 4     4     5
# 列位置选择列
tbl_df %>% select(1,2)
## # A tibble: 4 x 2
##    var1  var2
##   <int> <int>
## 1     1     2
## 2     2     3
## 3     3     4
## 4     4     5
# 列位置范围选择列
tbl_df %>% select(2:3)
## # A tibble: 4 x 2
##    var2 label
##   <int> <chr>
## 1     2 a    
## 2     3 b    
## 3     4 a    
## 4     5 c
# 字符向量选择列
tbl_df %>% select(c("var1","var2")) 
## # A tibble: 4 x 2
##    var1  var2
##   <int> <int>
## 1     1     2
## 2     2     3
## 3     3     4
## 4     4     5
# 位置向量选择列
tbl_df %>% select(c(1,2))
## # A tibble: 4 x 2
##    var1  var2
##   <int> <int>
## 1     1     2
## 2     2     3
## 3     3     4
## 4     4     5

反向选择

-符号来进行反向选择列。

# 引用选择列(反向)
tbl_df %>% select(-var1,-var2) 
## # A tibble: 4 x 1
##   label
##   <chr>
## 1 a    
## 2 b    
## 3 a    
## 4 c
# 范围引用选择列(反向)
tbl_df %>% select(-var1:-var2)
## # A tibble: 4 x 1
##   label
##   <chr>
## 1 a    
## 2 b    
## 3 a    
## 4 c
# 列位置选择列(反向)
tbl_df %>% select(-1,-2)
## # A tibble: 4 x 1
##   label
##   <chr>
## 1 a    
## 2 b    
## 3 a    
## 4 c
# 列位置范围选择列(反向)
tbl_df %>% select(-2:-3)
## # A tibble: 4 x 1
##    var1
##   <int>
## 1     1
## 2     2
## 3     3
## 4     4
# 字符向量选择列(反向)
tbl_df %>% select(-c("var1","var2")) 
## # A tibble: 4 x 1
##   label
##   <chr>
## 1 a    
## 2 b    
## 3 a    
## 4 c
# 位置向量选择列(反向)
tbl_df %>% select(-c(1,2))
## # A tibble: 4 x 1
##   label
##   <chr>
## 1 a    
## 2 b    
## 3 a    
## 4 c

匹配选择

还可以通过模式匹配的方式,批量选择列。

# 1.前缀匹配
tbl_df %>% select(starts_with("var")) 
## # A tibble: 4 x 2
##    var1  var2
##   <int> <int>
## 1     1     2
## 2     2     3
## 3     3     4
## 4     4     5
# 2.后缀匹配
tbl_df %>% select(ends_with("l")) 
## # A tibble: 4 x 1
##   label
##   <chr>
## 1 a    
## 2 b    
## 3 a    
## 4 c
# 3.包含匹配
tbl_df %>% select(contains("a")) 
## # A tibble: 4 x 3
##    var1  var2 label
##   <int> <int> <chr>
## 1     1     2 a    
## 2     2     3 b    
## 3     3     4 a    
## 4     4     5 c
# 4.正则匹配
tbl_df %>% select(matches("\\d")) 
## # A tibble: 4 x 2
##    var1  var2
##   <int> <int>
## 1     1     2
## 2     2     3
## 3     3     4
## 4     4     5
# 5.数字匹配
tbl_df %>% select(num_range("var",1:2)) 
## # A tibble: 4 x 2
##    var1  var2
##   <int> <int>
## 1     1     2
## 2     2     3
## 3     3     4
## 4     4     5
# 6.列名匹配
tbl_df %>% select(one_of(c("var1","var2"))) 
## # A tibble: 4 x 2
##    var1  var2
##   <int> <int>
## 1     1     2
## 2     2     3
## 3     3     4
## 4     4     5
# 反向匹配(以上6种方法都适用)
tbl_df %>% select(-one_of(c("var1","var2")))
## # A tibble: 4 x 1
##   label
##   <chr>
## 1 a    
## 2 b    
## 3 a    
## 4 c

其他选择

包括一些列顺序调整,选择最后一列等小技巧。

# 条件选择(选择所有数值列)
tbl_df %>% select_if(is.numeric)
## # A tibble: 4 x 2
##    var1  var2
##   <int> <int>
## 1     1     2
## 2     2     3
## 3     3     4
## 4     4     5
# 列顺序调整
tbl_df %>% select(var2,everything())
## # A tibble: 4 x 3
##    var2  var1 label
##   <int> <int> <chr>
## 1     2     1 a    
## 2     3     2 b    
## 3     4     3 a    
## 4     5     4 c
# 选择列的方式重命名列
tbl_df %>% select(rename_var1=var1) 
## # A tibble: 4 x 1
##   rename_var1
##         <int>
## 1           1
## 2           2
## 3           3
## 4           4
# 选择最后一列
tbl_df %>% select(last_col()) 
## # A tibble: 4 x 1
##   label
##   <chr>
## 1 a    
## 2 b    
## 3 a    
## 4 c
# 倒数第二列
tbl_df %>% select(last_col(1)) 
## # A tibble: 4 x 1
##    var2
##   <int>
## 1     2
## 2     3
## 3     4
## 4     5

列变形 mutate/transmute

mutatetransmute函数用来对数据框的列进行新增、修改、删除等操作,二者的使用方法基本相同,区别在于transmute函数会在进行操作后删除原有列,而mutate会保留原有列。

# 数据
tbl_df <- tibble(var1=1:4,var2=2:5,label=c("a","b","a","c"))

mutate

  • 单个模式
    单个模式中,可以完成对单列变形。
tbl_df %>% mutate(new1=var1,new2=new1+10)  # 新增列(先增列能被后增列引用)
## # A tibble: 4 x 5
##    var1  var2 label  new1  new2
##   <int> <int> <chr> <int> <dbl>
## 1     1     2 a         1    11
## 2     2     3 b         2    12
## 3     3     4 a         3    13
## 4     4     5 c         4    14
tbl_df %>% mutate(var1=NULL)  # 删除原列
## # A tibble: 4 x 2
##    var2 label
##   <int> <chr>
## 1     2 a    
## 2     3 b    
## 3     4 a    
## 4     5 c
tbl_df %>% mutate(var1=var1+1)  # 修改原列
## # A tibble: 4 x 3
##    var1  var2 label
##   <dbl> <int> <chr>
## 1     2     2 a    
## 2     3     3 b    
## 3     4     4 a    
## 4     5     5 c
var1 <- 11:14
tbl_df %>% mutate(var1=!!var1)  # 新增列(非引用方式)
## # A tibble: 4 x 3
##    var1  var2 label
##   <int> <int> <chr>
## 1    11     2 a    
## 2    12     3 b    
## 3    13     4 a    
## 4    14     5 c
  • 批量模式
    批量模式中,可以
# 全部列
tbl_df %>% mutate_all(rev)  # 单函数(不产生新列)
## # A tibble: 4 x 3
##    var1  var2 label
##   <int> <int> <chr>
## 1     4     5 c    
## 2     3     4 a    
## 3     2     3 b    
## 4     1     2 a
tbl_df %>% mutate_all(list(rev=rev)) # 单函数(产生新列)
## # A tibble: 4 x 6
##    var1  var2 label var1_rev var2_rev label_rev
##   <int> <int> <chr>    <int>    <int> <chr>    
## 1     1     2 a            4        5 c        
## 2     2     3 b            3        4 a        
## 3     3     4 a            2        3 b        
## 4     4     5 c            1        2 a
tbl_df %>% mutate_all(list(rev=rev,sort=sort))  # 多函数
## # A tibble: 4 x 9
##    var1  var2 label var1_rev var2_rev label_rev
##   <int> <int> <chr>    <int>    <int> <chr>    
## 1     1     2 a            4        5 c        
## 2     2     3 b            3        4 a        
## 3     3     4 a            2        3 b        
## 4     4     5 c            1        2 a        
## # … with 3 more variables: var1_sort <int>,
## #   var2_sort <int>, label_sort <chr>
# 指定列
tbl_df %>% mutate_at(c("var1","var2"),exp)  # 列名+单函数
## # A tibble: 4 x 3
##    var1   var2 label
##   <dbl>  <dbl> <chr>
## 1  2.72   7.39 a    
## 2  7.39  20.1  b    
## 3 20.1   54.6  a    
## 4 54.6  148.   c
tbl_df %>% mutate_at(c("var1","var2"),~round(log(.),1)) # 列名+匿名函数
## # A tibble: 4 x 3
##    var1  var2 label
##   <dbl> <dbl> <chr>
## 1   0     0.7 a    
## 2   0.7   1.1 b    
## 3   1.1   1.4 a    
## 4   1.4   1.6 c
tbl_df %>% mutate_at(c(1,2),exp)  # 列位置+单函数
## # A tibble: 4 x 3
##    var1   var2 label
##   <dbl>  <dbl> <chr>
## 1  2.72   7.39 a    
## 2  7.39  20.1  b    
## 3 20.1   54.6  a    
## 4 54.6  148.   c
tbl_df %>% mutate_at(c(1,2),list(log=log,exp=exp)) # 列位置+多函数
## # A tibble: 4 x 7
##    var1  var2 label var1_log var2_log var1_exp var2_exp
##   <int> <int> <chr>    <dbl>    <dbl>    <dbl>    <dbl>
## 1     1     2 a        0        0.693     2.72     7.39
## 2     2     3 b        0.693    1.10      7.39    20.1 
## 3     3     4 a        1.10     1.39     20.1     54.6 
## 4     4     5 c        1.39     1.61     54.6    148.
tbl_df %>% mutate_at(vars(matches("\\d")),exp) # vars方式
## # A tibble: 4 x 3
##    var1   var2 label
##   <dbl>  <dbl> <chr>
## 1  2.72   7.39 a    
## 2  7.39  20.1  b    
## 3 20.1   54.6  a    
## 4 54.6  148.   c
# 条件列
tbl_df %>% mutate_if(is.character,rev) # 单函数
## # A tibble: 4 x 3
##    var1  var2 label
##   <int> <int> <chr>
## 1     1     2 c    
## 2     2     3 a    
## 3     3     4 b    
## 4     4     5 a
tbl_df %>% mutate_if(is.numeric,list(log=log,exp=exp)) # 多函数
## # A tibble: 4 x 7
##    var1  var2 label var1_log var2_log var1_exp var2_exp
##   <int> <int> <chr>    <dbl>    <dbl>    <dbl>    <dbl>
## 1     1     2 a        0        0.693     2.72     7.39
## 2     2     3 b        0.693    1.10      7.39    20.1 
## 3     3     4 a        1.10     1.39     20.1     54.6 
## 4     4     5 c        1.39     1.61     54.6    148.

transmute

  • 单个模式
tbl_df %>% transmute(new1=var1,new2=new1+10)  # 新增列(先增列能被后增列引用)
## # A tibble: 4 x 2
##    new1  new2
##   <int> <dbl>
## 1     1    11
## 2     2    12
## 3     3    13
## 4     4    14
tbl_df %>% transmute(var1=var1+1)  # 覆盖原列
## # A tibble: 4 x 1
##    var1
##   <dbl>
## 1     2
## 2     3
## 3     4
## 4     5
var1 <- 11:14
tbl_df %>% transmute(var1=!!var1)  # 新增列(非引用方式)
## # A tibble: 4 x 1
##    var1
##   <int>
## 1    11
## 2    12
## 3    13
## 4    14
  • 批量模式
# 全部列
tbl_df %>% transmute_all(rev)  # 单函数(不产生新列)
## # A tibble: 4 x 3
##    var1  var2 label
##   <int> <int> <chr>
## 1     4     5 c    
## 2     3     4 a    
## 3     2     3 b    
## 4     1     2 a
tbl_df %>% transmute_all(list(rev=rev)) # 单函数(产生新列)
## # A tibble: 4 x 3
##   var1_rev var2_rev label_rev
##      <int>    <int> <chr>    
## 1        4        5 c        
## 2        3        4 a        
## 3        2        3 b        
## 4        1        2 a
tbl_df %>% transmute_all(list(rev=rev,sort=sort))  # 多函数
## # A tibble: 4 x 6
##   var1_rev var2_rev label_rev var1_sort var2_sort
##      <int>    <int> <chr>         <int>     <int>
## 1        4        5 c                 1         2
## 2        3        4 a                 2         3
## 3        2        3 b                 3         4
## 4        1        2 a                 4         5
## # … with 1 more variable: label_sort <chr>
tbl_df %>% transmute_all(list(rev=~rev(.),sort=~sort(.)))  # 多匿名函数
## # A tibble: 4 x 6
##   var1_rev var2_rev label_rev var1_sort var2_sort
##      <int>    <int> <chr>         <int>     <int>
## 1        4        5 c                 1         2
## 2        3        4 a                 2         3
## 3        2        3 b                 3         4
## 4        1        2 a                 4         5
## # … with 1 more variable: label_sort <chr>
# 指定列
tbl_df %>% transmute_at(c("var1","var2"),exp)  # 列名+单函数
## # A tibble: 4 x 2
##    var1   var2
##   <dbl>  <dbl>
## 1  2.72   7.39
## 2  7.39  20.1 
## 3 20.1   54.6 
## 4 54.6  148.
tbl_df %>% transmute_at(c("var1","var2"),~round(log(.),1)) # 列名+匿名函数
## # A tibble: 4 x 2
##    var1  var2
##   <dbl> <dbl>
## 1   0     0.7
## 2   0.7   1.1
## 3   1.1   1.4
## 4   1.4   1.6
tbl_df %>% transmute_at(c(1,2),exp)  # 列位置+单函数
## # A tibble: 4 x 2
##    var1   var2
##   <dbl>  <dbl>
## 1  2.72   7.39
## 2  7.39  20.1 
## 3 20.1   54.6 
## 4 54.6  148.
tbl_df %>% transmute_at(c(1,2),list(log=log,exp=exp)) # 列位置+多函数
## # A tibble: 4 x 4
##   var1_log var2_log var1_exp var2_exp
##      <dbl>    <dbl>    <dbl>    <dbl>
## 1    0        0.693     2.72     7.39
## 2    0.693    1.10      7.39    20.1 
## 3    1.10     1.39     20.1     54.6 
## 4    1.39     1.61     54.6    148.
tbl_df %>% transmute_at(vars(matches("\\d")),exp) # vars方式
## # A tibble: 4 x 2
##    var1   var2
##   <dbl>  <dbl>
## 1  2.72   7.39
## 2  7.39  20.1 
## 3 20.1   54.6 
## 4 54.6  148.
# 条件列
tbl_df %>% transmute_if(is.character,rev) # 单函数
## # A tibble: 4 x 1
##   label
##   <chr>
## 1 c    
## 2 a    
## 3 b    
## 4 a
tbl_df %>% transmute_if(is.numeric,list(log=log,exp=exp)) # 多函数
## # A tibble: 4 x 4
##   var1_log var2_log var1_exp var2_exp
##      <dbl>    <dbl>    <dbl>    <dbl>
## 1    0        0.693     2.72     7.39
## 2    0.693    1.10      7.39    20.1 
## 3    1.10     1.39     20.1     54.6 
## 4    1.39     1.61     54.6    148.
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容