r语言depmix_R语言:dplyr介绍

本文介绍了R语言dplyr包的常用数据操作动词,如filter()、arrange()、select()和mutate(),并以nycflights13数据集为例展示具体应用,帮助理解如何高效处理数据框。
摘要由CSDN通过智能技术生成

翻译自:??dplyr->vignettes->dplyr::dplyr——Introduction to dplyr。

当用数据工作时,你必须:

1. 想出你想做什么

2. 用计算机程序结构描述那些工作

3. 执行程序

Dplyr包使这些步骤变得更快更容易:

1. 通过约束你的选择,它可以帮助你思考数据操作中的难题。

2. 它提供简单的“动词”、以及相应的大量常规数据计算任务的方程,来帮助你将你的想法转换为代码。

3. 它使用了高效率的后端,所以你花在等待电脑响应的时间变少了。

这个文档向你介绍了dplyr的基本工具集,并展示了怎样将它们应用于数据框。也可使用dplyr的扩展包dbplyr包来处理数据库。一旦你已经安装,可以读入vignetter(“dbplyr”)(这条语句等同于??dbplyr)来学习更多知识。

数据:nycflights13包

为了探索dplyr包的基本数据操作动词,我们将使用nycflights13:flights数据集。这个数据集包含了2013年从纽约起飞的336776次航班。数据来源于美国

注:在首次使用nycflights13包时,需要 :

install.packages("nycflight13")

我们可以查看一下数据集内容:

> library(nycflights13)

> dim(flights)

[1] 336776 19

> class(flights)

[1] "tbl_df" "tbl" "data.frame"

[2] > names(flights)

[3] [1] "year" "month" "day"

[4] "dep_time" "sched_dep_time" "dep_delay"

[7] "arr_time" "sched_arr_time" "arr_delay"

[10] "carrier" "flight" "tailnum"

[13] "origin" "dest" "air_time"

[16] "distance" "hour" "minute"

[19] "time_hour"

> flights

# A tibble: 336,776 x 19

year month day dep_time sched_dep_time dep_delay arr_time

1 2013 1 1 517 515 2 830

2 2013 1 1 533 529 4 850

3 2013 1 1 542 540 2 923

4 2013 1 1 544 545 -1 1004

5 2013 1 1 554 600 -6 812

6 2013 1 1 554 558 -4 740

7 2013 1 1 555 600 -5 913

8 2013 1 1 557 600 -3 709

9 2013 1 1 557 600 -3 838

10 2013 1 1 558 600 -2 753

# ... with 336,766 more rows, and 12 more variables:

# sched_arr_time , arr_delay , carrier ,

# flight , tailnum , origin , dest ,

# air_time , distance , hour , minute ,

# time_hour

注意nycflights13::flights是一个tibble数据类型,是数据框(data.frame)类型的重新塑造。它对于大型数据集特别有用,因为它仅仅输出最前面几行的数据(节省时间)。你可以从这里

单表动词

Dplyr目的是为每一个基本数据操作动作提供一个函数:

1. filter()根据它们的值选择实例。

2. arrange()将实例重新排列。

3. select()和rename():根据它们的变量名选择变量。

4. mutate()和transmute():添加新的变量,这些变量是现有变量的函数。

5. summarise():将多个值压缩为一个值。

6. sample_n()和sample_frac():获得一个随机样本。

fliter():过滤行

fliter()允许你从数据框中选择出一个多行子集。与所有的单表动词(single verbs)一样,它的第一个参数就是tibble(或数据框)。第二个和随后的参数引用该数据框中的变量,选择表达式为真的行。

例如:选择1月1日的所有航班。

> filter(flights,month==1,day==1)

# A tibble: 842 x 19

year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time arr_delay

1 2013 1 1 517 515 2 830 819 11

2 2013 1 1 533 529 4 850 830 20

3 2013 1 1 542 540 2 923 850 33

4 2013 1 1 544 545 -1 1004 1022 -18

5 2013 1 1 554 600 -6 812 837 -25

6 2013 1 1 554 558 -4 740 728 12

7 2013 1 1 555 600 -5 913 854 19

8 2013 1 1 557 600 -3 709 723 -14

9 2013 1 1 557 600 -3 838 846 -8

10 2013 1 1 558 600 -2 753 745 8

# ... with 832 more rows, and 10 more variables: carrier , flight , tailnum ,

# origin , dest , air_time , distance , hour , minute ,

# time_hour

大致与下述基本R代码作用相同:

> flights[flights$month==1&flights$day==1,]

arrange():行排列

Arrange()的功能与filter()相似,但除了过滤和选择行之外,它还会对其进行排列。它需要一个数据框和一组列名称(或者更复杂的表达式)来进行排序。如果你使用了不止一个列名,每一个附加的列将被打断插入先前的列值当中。

> arrange(flights,year,month,day)

# A tibble: 336,776 x 19

year month day dep_time sched_dep_time dep_delay arr_time

1 2013 1 1 517 515 2 830

2 2013 1 1 533 529 4 850

3 2013 1 1 542 540 2 923

4 2013 1 1 544 545 -1 1004

5 2013 1 1 554 600 -6 812

6 2013 1 1 554 558 -4 740

7 2013 1 1 555 600 -5 913

8 2013 1 1 557 600 -3 709

9 2013 1 1 557 600 -3 838

10 2013 1 1 558 600 -2 753

# ... with 336,766 more rows, and 12 more variables:

# sched_arr_time , arr_delay , carrier ,

# flight , tailnum , origin , dest ,

# air_time , distance , hour , minute ,

# time_hour

使用desc()对一个列进行降序排列。

> arrange(flights,desc(arr_delay))

# A tibble: 336,776 x 19

year month day dep_time sched_dep_time dep_delay arr_time

1 2013 1 9 641 900 1301 1242

2 2013 6 15 1432 1935 1137 1607

3 2013 1 10 1121 1635 1126 1239

4 2013 9 20 1139 1845 1014 1457

5 2013 7 22 845 1600 1005 1044

6 2013 4 10 1100 1900 960 1342

7 2013 3 17 2321 810 911 135

8 2013 7 22 2257 759 898 121

9 2013 12 5 756 1700 896 1058

10 2013 5 3 1133 2055 878 1250

# ... with 336,766 more rows, and 12 more variables:

# sched_arr_time , arr_delay , carrier ,

# flight , tailnum , origin , dest ,

# air_time , distance , hour , minute ,

# time_hour

select():选择列

你经常需要处理有很多列的巨大数据集,可实际上你感兴趣的只有几行。select()使你能够快速聚焦在有用的数据子集上,通常该操作只用于数值型变量:

> select(flights,year,month,day)

# A tibble: 336,776 x 3

year month day

1 2013 1 1

2 2013 1 1

3 2013 1 1

4 2013 1 1

5 2013 1 1

6 2013 1 1

7 2013 1 1

8 2013 1 1

9 2013 1 1

10 2013 1 1

# ... with 336,766 more rows

> select(flights,year:day)

# A tibble: 336,776 x 3

year month day

1 2013 1 1

2 2013 1 1

3 2013 1 1

4 2013 1 1

5 2013 1 1

6 2013 1 1

7 2013 1 1

8 2013 1 1

9 2013 1 1

10 2013 1 1

# ... with 336,766 more rows

> select(flights,-(year:day))

# A tibble: 336,776 x 16

dep_time sched_dep_time dep_delay arr_time sched_arr_time arr_delay

1 517 515 2 830 819 11

2 533 529 4 850 830 20

3 542 540 2 923 850 33

4 544 545 -1 1004 1022 -18

5 554 600 -6 812 837 -25

6 554 558 -4 740 728 12

7 555 600 -5 913 854 19

8 557 600 -3 709 723 -14

9 557 600 -3 838 846 -8

10 558 600 -2 753 745 8

# ... with 336,766 more rows, and 10 more variables: carrier ,

# flight , tailnum , origin , dest ,

# air_time , distance , hour , minute ,

# time_hour

你可以在select()中使用许多辅助函数,例如starts_with(),ends_with(),matches(),contains()。这些函数可以让你快速匹配符合某些条件的巨大的变量块。输入?Select()可以了解更多详细资料。

你可以使用select()和实名参数来重新命名变量:

> select(flights,tail_num=tailnum)

# A tibble: 336,776 x 1

tail_num

1 N14228

2 N24211

3 N619AA

4 N804JB

5 N668DN

6 N39463

7 N516JB

8 N829AS

9 N593JB

10 N3ALAA

# ... with 336,766 more rows

但是由于select()将所有没有明确提到的变量都删除了,所以不是很有用。因而,我们可以使用rename()来进行变量重命名:

> rename(flights,tail_num=tailnum)

# A tibble: 336,776 x 19

year month day dep_time sched_dep_time dep_delay arr_time

1 2013 1 1 517 515 2 830

2 2013 1 1 533 529 4 850

3 2013 1 1 542 540 2 923

4 2013 1 1 544 545 -1 1004

5 2013 1 1 554 600 -6 812

6 2013 1 1 554 558 -4 740

7 2013 1 1 555 600 -5 913

8 2013 1 1 557 600 -3 709

9 2013 1 1 557 600 -3 838

10 2013 1 1 558 600 -2 753

# ... with 336,766 more rows, and 12 more variables:

# sched_arr_time , arr_delay , carrier ,

# flight , tail_num , origin , dest ,

# air_time , distance , hour , minute ,

# time_hour

mutate():添加新列

除了选择现有列的集合之外,添加新列通常也很有用,这些新列是现有列的函数。这个工作由mutate()完成:

> mutate(flights,gain=arr_delay-dep_delay,speed=distance/air_time*60)

# A tibble: 336,776 x 21

year month day dep_time sched_dep_time dep_delay arr_time

1 2013 1 1 517 515 2 830

2 2013 1 1 533 529 4 850

3 2013 1 1 542 540 2 923

4 2013 1 1 544 545 -1 1004

5 2013 1 1 554 600 -6 812

6 2013 1 1 554 558 -4 740

7 2013 1 1 555 600 -5 913

8 2013 1 1 557 600 -3 709

9 2013 1 1 557 600 -3 838

10 2013 1 1 558 600 -2 753

# ... with 336,766 more rows, and 14 more variables:

# sched_arr_time , arr_delay , carrier ,

# flight , tailnum , origin , dest ,

# air_time , distance , hour , minute ,

# time_hour , gain , speed

Dplyr::mutate()与基础函数transform()相似,但是允许你引用刚刚创建的列:

> mutate(flights,gain=arr_delay-dep_delay,gain_per_hour=gain/(air_time/60))

# A tibble: 336,776 x 21

year month day dep_time sched_dep_time dep_delay arr_time

1 2013 1 1 517 515 2 830

2 2013 1 1 533 529 4 850

3 2013 1 1 542 540 2 923

4 2013 1 1 544 545 -1 1004

5 2013 1 1 554 600 -6 812

6 2013 1 1 554 558 -4 740

7 2013 1 1 555 600 -5 913

8 2013 1 1 557 600 -3 709

9 2013 1 1 557 600 -3 838

10 2013 1 1 558 600 -2 753

# ... with 336,766 more rows, and 14 more variables:

# sched_arr_time , arr_delay , carrier ,

# flight , tailnum , origin , dest ,

# air_time , distance , hour , minute ,

# time_hour , gain , gain_per_hour

如果你仅仅只想保留新的变量,使用transmute():

> transmute(flights,gain=arr_delay-dep_delay,gain_per_hour=gain/(air_time/60))

# A tibble: 336,776 x 2

gain gain_per_hour

1 9 2.378855

2 16 4.229075

3 31 11.625000

4 -17 -5.573770

5 -19 -9.827586

6 16 6.400000

7 24 9.113924

8 -11 -12.452830

9 -5 -2.142857

10 10 4.347826

# ... with 336,766 more rows

summarise():归纳值

最后一个动词是summarise(),它将一个数据框折叠为一个简单汇总集。

> summarise(flights,delay=mean(dep_delay,na.rm = TRUE))

# A tibble: 1 x 1

delay

1 12.63907

在我们学习下面的group by()之前,它并不是很有用。

Sample_n()和sample_frac():随机选取行样本

你可以使用sample()和sample_frac()获得一个行的随机样本。使用sample_n()可选择固定的行数,sample_frac()可选择占总行数固定比例的行数。

> sample_n(flights,10)

# A tibble: 10 x 19

year month day dep_time sched_dep_time dep_delay arr_time

1 2013 11 18 901 903 -2 1216

2 2013 3 9 2106 2110 -4 2149

3 2013 8 27 1713 1711 2 1830

4 2013 10 3 2312 2159 73 9

5 2013 5 26 1803 1720 43 2104

6 2013 2 24 558 600 -2 715

7 2013 7 8 956 959 -3 1231

8 2013 6 28 846 815 31 1026

9 2013 6 21 901 900 1 1116

10 2013 4 27 1224 1130 54 1337

# ... with 12 more variables: sched_arr_time , arr_delay ,

# carrier , flight , tailnum , origin , dest ,

# air_time , distance , hour , minute ,

# time_hour

> sample_frac(flights,0.01)

# A tibble: 3,368 x 19

year month day dep_time sched_dep_time dep_delay arr_time

1 2013 12 20 1134 1135 -1 1334

2 2013 2 10 624 625 -1 853

3 2013 12 4 1814 1800 14 1952

4 2013 7 23 725 735 -10 1003

5 2013 10 20 959 1000 -1 1054

6 2013 2 8 632 630 2 852

7 2013 3 15 1545 1435 70 1837

8 2013 3 3 1924 1930 -6 2053

9 2013 10 3 1559 1559 0 1814

10 2013 4 7 1642 1645 -3 1745

# ... with 3,358 more rows, and 12 more variables: sched_arr_time ,

# arr_delay , carrier , flight , tailnum ,

# origin , dest , air_time , distance , hour ,

# minute , time_hour

使用replace=TRUE时为有放回的取样(即有可能重复取样)。如果需要,可以用weight参数来对取样的数据进行权重设置。

共性

你可能已经注意到,所有这些动词的语法和功能都非常相似:

(1)第一个参数是一个数据框

(2)后面的参数描述对数据框做些什么。你可以直接指定数据框中的列而不需要$.

(3)结果为一个新的数据框。

将这些属性组合在一起,就可以很容易地将多个简单步骤组合在一起,从而实现一个复杂的结果。

这五组函数提供了数据操作的基本语言。基本上,你可以仅仅用这五个有用的方法修剪一个简洁的数据框:你可以对行进行排列(arrange()),挑选出需要观察的或感兴趣的变量(filter()或select()),添加新的变量且这些变量是现有变量的函数(mutate()),或者折叠许多值获得一个综述值(summarise())。该语言的剩余部分为这五个函数在不同数据类型中的应用。例如,我将要讨论这些函数怎样处理分组数据。

操作模式

Dplyr动词可以根据它们所完成的操作类型进行分类(我们有时会说是它们的语义,也就是它们的含义)。最重要和最有用的区别在分组和未分组操作之间。另外,领会select()和mutate()之间的差异是非常有帮助的。

分组操作

Dplyr动词本身非常有用,但你把它们应用到一个数据集中已分组的观测集时,它们会变得更加强大。在dplyr中,你可以使用group_by()函数来完成这一操作,它将一个数据集分解为指定的行组。然后当你把上面的动词应用到结果对象上时,它们就会被自动“分组”应用。

*分组select()和不分组select()一样,除了总是保留分组变量。

*分组arrange()和不分组的相同,除非你设置by_group=TRUE,在这种情况下,它会首先对分组变量进行排序。

*mutate()和filter()非常适合与窗口函数(像rank()或mix(x)==x)一起使用,窗口函数在vignette(“window—function”)中有详细描述。

*sample_n和sample_frac()对每个组使用指定的行数/比例值(分数)进行抽样。

*summarise()对每个组计算汇总值。

在接下来的例子中,我们将完整的数据集分割为一些单独部分,然后对每一部分进行汇总,计算航班的数量(count=()),计算平均距离(dist=mean(distance,na.rm=TRUE)),计算平均延迟时间(delay=mean(arr_delay,na.rm=TRUE))。然后我们使用ggplot2展示这些结果。

library(dplyr)

library(nycflights13)

library(ggplot2)

by_tailnum

delay

count=n(),

dist=mean(distance,na.rm = TRUE),

delay=mean(arr_delay,na.rm = TRUE))

delay20,dist<2000)

#有趣的是,一个飞机的平均延时时间与平均飞行距离之间几乎无关。

ggplot(delay,aes(dist,delay))+

+ geom_point(aes(size=count),alpha=1/2)+

+ geom_smooth()+

+ scale_size_area()

你将summarise()和聚合函数一起使用,输入一个向量,返回一个单值。R基础包中有很多这样函数,例如:min(),max(),mean(),sum(),sd(),median(),IQR()等。Dply包也提供了几个:

n():目前每个分组观测值得数量

n_distinct(x):x中不重复值的数量,与length(unique())作用相同。

First(x)、last(x)、nth(x)——它们的作用与x[1]、x[length(x)]、x[n]相似,但是如果缺少了值,就可以对结果进行更多的控制。

例如,可以用这些函数找出去每一个可能目的地的飞机数量和航班数量。

> destinations

> summarise(destinations,

planes=n_distinct(tailnum),

flights+ =n()

)

# A tibble: 105 x 3

dest planes flights

1 ABQ 108 254

2 ACK 58 265

3 ALB 172 439

4 ANC 6 8

5 ATL 1180 17215

6 AUS 993 2439

7 AVL 159 275

8 BDL 186 443

9 BGR 46 375

10 BHM 45 297

# ... with 95 more rows

当你使用多个变量进行分组操作后,每汇总一个分组都会删去相应的分组等级。这使我们可以很容易地对数据集进行逐步的整合:

> daily

> per_day per_day

# A tibble: 365 x 4

# Groups: year, month [?]

year month day flights

1 2013 1 1 842

2 2013 1 2 943

3 2013 1 3 914

4 2013 1 4 915

5 2013 1 5 720

6 2013 1 6 832

7 2013 1 7 933

8 2013 1 8 899

9 2013 1 9 902

10 2013 1 10 932

# ... with 355 more rows

> per_month

> per_month

# A tibble: 12 x 3

# Groups: year [?]

year month flights

1 2013 1 27004

2 2013 2 24951

3 2013 3 28834

4 2013 4 28330

5 2013 5 28796

6 2013 6 28243

7 2013 7 29425

8 2013 8 29327

9 2013 9 27574

10 2013 10 28889

11 2013 11 27268

12 2013 12 28135

> per_year

> per_year

# A tibble: 1 x 2

year flights

1 2013 336776

但是如果你像这样逐步整合汇总时需要小心:这对求和(sums)和汇总数量(counts)是可以的,但是你需要考虑加权的均值和方差(对于中位数来说这是不可能做到的)。

选择操作

dplyr的一个吸引人的特性是你可以从tibble中引用一些列,就好像它们是常规变量一样。但是,引用无修饰列名(bare column names)的语法一致性隐藏了变量之间的语义差异。提供给select()函数的列名与提供给mutate()函数的列名的含义不同。

选择操作会预估列名和位置。因此,当你使用select()调用基本位置变量名时,实际上代表了它们自己在tibble中的位置。下面的调用与dplyr的方法完全相同:

> #'year'代表数字1

> select(flights,year)

# A tibble: 336,776 x 1

year

1 2013

2 2013

3 2013

4 2013

5 2013

6 2013

7 2013

8 2013

9 2013

10 2013

# ... with 336,766 more rows> select(flights,1)# A tibble: 336,776 x 1

> select(flights,1)

year

1 2013

2 2013

3 2013

4 2013

5 2013

6 2013

7 2013

8 2013

9 2013

10 2013

# ... with 336,766 more rows

同样的,你也无法从周围上下文中引用与列名相同的变量。例如下面的例子,select中的year仍代表1,而不是5。

> year

> select(flights,year)

# A tibble: 336,776 x 1

year

1 2013

2 2013

3 2013

4 2013

5 2013

6 2013

7 2013

8 2013

9 2013

10 2013

# ... with 336,766 more rows

一个非常有用的微妙之处是:只可以使用无修饰列名去选择调用像c(year,month,day)或者year:day这样的句子。在其他所有例子中,若数据框的列没有放在列引用位置(包裹在函数中),允许你在辅助选择中引用上下文变量:

> year

> select(flights,starts_with(year))

# A tibble: 336,776 x 2

dep_time dep_delay

1 517 2

2 533 4

3 542 2

4 544 -1

5 554 -6

6 554 -4

7 555 -5

8 557 -3

9 557 -3

10 558 -2

# ... with 336,766 more rows

这些语言通常非常直观,但要注意细微的差异:

> year

> select(flights,year,identity(year))

# A tibble: 336,776 x 2

year sched_dep_time

1 2013 515

2 2013 529

3 2013 540

4 2013 545

5 2013 600

6 2013 558

7 2013 600

8 2013 600

9 2013 600

10 2013 600

# ... with 336,766 more rows

第一个参数year代表它自己的位置1,第二个参数year会在周围上下文中进行评估,它表示数字5,即位置5。

长期以来,select()仅仅用来理解列的位置。从dplyr 0.6开始,它现在也可以理解列名。这使得使用select()进行编程更加容易:

> var

> select(flights,var,'day')

# A tibble: 336,776 x 3

year month day

1 2013 1 1

2 2013 1 1

3 2013 1 1

4 2013 1 1

5 2013 1 1

6 2013 1 1

7 2013 1 1

8 2013 1 1

9 2013 1 1

10 2013 1 1

# ... with 336,766 more rows

注意上面的代码有点不安全,因为你可能在tibble中添加了名为var的列,或者你可能将代码应用到了另一个包含这个列名的数据框上。为了避免这些问题,你可以将变量包裹在identity()函数中,就像我们上面提到的那样,因为这样会忽略列名。但是,一个更加直白和常用的方法是,所有的dplyr动词(verbs)中可以使用‘!!’操作符引用变量,它告诉dplyr忽略数据框,直接查看文本:

> #创建一个新的变量

> flights$vars

#如果你评估‘vars’时加上‘!!’操作符,这个新变量列就不会造成影响

> vars

> select(flights,!!vars)

# A tibble: 336,776 x 3

year month day

1 2013 1 1

2 2013 1 1

3 2013 1 1

4 2013 1 1

5 2013 1 1

6 2013 1 1

7 2013 1 1

8 2013 1 1

9 2013 1 1

10 2013 1 1

# ... with 336,766 more rows

在常规方程中使用dplyr时,这个方程非常有用,想学习更多可参考vignette(‘programming’)。但理解你所引用的动词的语义也是很重要的,也就是他们所理解的值。就像我们刚才提到的,select()支持列名和列的位置,但是在其他动词中情况并非如此,例如mutate(),因为他们语义不同。

变异(mutating)操作

Mutate的语义和selection的语义非常不同。Select()参数为列名或列位置,mutate()参数为列向量。我们将创建一个小的tibble来清晰了解一下这个不同:

> df

当我们用select()时,无修饰列名代表它们在tibble中的位置。而对于mutate()却是另一个含义,列标识代表存储在tibble中的整个列向量。想一下如果我们给mutate()一个字符串或一个数字会发生什么:

> mutate(df,'year',2)

# A tibble: 336,776 x 6

year month day dep_time `"year"` `2`

1 2013 1 1 517 year 2

2 2013 1 1 533 year 2

3 2013 1 1 542 year 2

4 2013 1 1 544 year 2

5 2013 1 1 554 year 2

6 2013 1 1 554 year 2

7 2013 1 1 555 year 2

8 2013 1 1 557 year 2

9 2013 1 1 557 year 2

10 2013 1 1 558 year 2

# ... with 336,766 more rows

Mutate()得到长度为1的向量,它将其解释为数据框中的新列,这些向量循环匹配行数。这就是为什么提供像‘year’+10这样的表达式是没有意义的,这个求和是给一个字符串‘year’加10!正确的表达式是(不带引号):

> mutate(df,year+10)

# A tibble: 336,776 x 5

year month day dep_time `year + 10`

1 2013 1 1 517 2023

2 2013 1 1 533 2023

3 2013 1 1 542 2023

4 2013 1 1 544 2023

5 2013 1 1 554 2023

6 2013 1 1 554 2023

7 2013 1 1 555 2023

8 2013 1 1 557 2023

9 2013 1 1 557 2023

10 2013 1 1 558 2023

# ... with 336,766 more rows

同样,如果这些值表示一个有效的列,则可以从上下文中引用值。它们必须长度为1(然后循环得到列)或者与数据框有相同的行数。下面我们将创建一个新向量,然后添加到数据框:

> var

> mutate(df,new=var)

# A tibble: 336,776 x 5

year month day dep_time new

1 2013 1 1 517 1

2 2013 1 1 533 2

3 2013 1 1 542 3

4 2013 1 1 544 4

5 2013 1 1 554 5

6 2013 1 1 554 6

7 2013 1 1 555 7

8 2013 1 1 557 8

9 2013 1 1 557 9

10 2013 1 1 558 10

# ... with 336,766 more rows

一个恰当的例子是group_by()。当你认为它选择了语义,它实际有包含mutate语义含义。这是十分方便的,因为这样允许用一个修改的列进行分组:

> group_by(df,month)

# A tibble: 336,776 x 4

# Groups: month [12]

year month day dep_time

1 2013 1 1 517

2 2013 1 1 533

3 2013 1 1 542

4 2013 1 1 544

5 2013 1 1 554

6 2013 1 1 554

7 2013 1 1 555

8 2013 1 1 557

9 2013 1 1 557

10 2013 1 1 558

# ... with 336,766 more rows

> group_by(df,month=as.factor(month))

# A tibble: 336,776 x 4

# Groups: month [12]

year month day dep_time

1 2013 1 1 517

2 2013 1 1 533

3 2013 1 1 542

4 2013 1 1 544

5 2013 1 1 554

6 2013 1 1 554

7 2013 1 1 555

8 2013 1 1 557

9 2013 1 1 557

10 2013 1 1 558

# ... with 336,766 more rows

这就是为什么不能提供一个列名给group_by(),这就相当于创建了一个新的列,其中包含的字符串循环的次数为整个行数。

> group_by(df,'month')

# A tibble: 336,776 x 5

# Groups: "month" [1]

year month day dep_time `"month"`

1 2013 1 1 517 month

2 2013 1 1 533 month

3 2013 1 1 542 month

4 2013 1 1 544 month

5 2013 1 1 554 month

6 2013 1 1 554 month

7 2013 1 1 555 month

8 2013 1 1 557 month

9 2013 1 1 557 month

10 2013 1 1 558 month

# ... with 336,766 more rows

因为有时候使用select语义也很有用,所以添加了group_by_at()变体。在dplyr中,变体后缀_at()在他们的第二个参数中支持select语义。你只需要用vars()包裹这个选择:

> group_by_at(df,vars(year:day))

# A tibble: 336,776 x 4

# Groups: year, month, day [365]

year month day dep_time

1 2013 1 1 517

2 2013 1 1 533

3 2013 1 1 542

4 2013 1 1 544

5 2013 1 1 554

6 2013 1 1 554

7 2013 1 1 555

8 2013 1 1 557

9 2013 1 1 557

10 2013 1 1 558

# ... with 336,766 more rows

你可以了解更多_at()和_if()变体在?Scoped帮助页面。

管道

就没有附带结果的函数调用而言,Dplyr的API是功能性的,你必须不停的保存它们的结果,这使得你无法写出特别优雅的代码,特别是想要一次性执行很多操作的时候,你却不得不一步一步执行:

> a1

> a2

Adding missing grouping variables: `year`, `month`, `day`

> a3

+ arr=mean(arr_delay,na.rm = TRUE),

+ dep=mean(dep_delay,na.rm = TRUE))

> a430|dep>30)

或者你不想命名这些中间结果并想一次完成,就需要在其他函数中包裹函数调用:

> filter(

+ summarise(

+ select(

+ group_by(flights,year,month,day),

+ arr_delay,dep_delay

+ ),

+ arr=mean(arr_delay,na.rm=TRUE),

+ dep=mean(dep_delay,na.rm = TRUE)

+ ),

+ arr>30|dep>30)

Adding missing grouping variables: `year`, `month`, `day`

# A tibble: 49 x 5

# Groups: year, month [11]

year month day arr dep

1 2013 1 16 34.24736 24.61287

2 2013 1 31 32.60285 28.65836

3 2013 2 11 36.29009 39.07360

4 2013 2 27 31.25249 37.76327

5 2013 3 8 85.86216 83.53692

6 2013 3 18 41.29189 30.11796

7 2013 4 10 38.41231 33.02368

8 2013 4 12 36.04814 34.83843

9 2013 4 18 36.02848 34.91536

10 2013 4 19 47.91170 46.12783

# ... with 39 more rows

这使得程序变得晦涩难懂,因为操作的顺序是由内向外的。因此,参数与函数之间有一段很长的距离。为了解决这个问题,dplyr提供了来自于magrittr的%>%操作,将x%>%f(x)转换为f(x,y),所以你可以使用它重写复杂的操作,然后i可以从左向右,从上到下读取:

> flights%>%

+ group_by(year,month,day)%>%

+ select(arr_delay,dep_delay)%>%

+ summarise(+ arr=mean(arr_delay,na.rm = TRUE),

+ dep=mean(dep_delay,na.rm = TRUE)+ )%>%

+ filter(arr>30|dep>30)

Adding missing grouping variables: `year`, `month`, `day`

# A tibble: 49 x 5

# Groups: year, month [11]

year month day arr dep

1 2013 1 16 34.24736 24.61287

2 2013 1 31 32.60285 28.65836

3 2013 2 11 36.29009 39.07360

4 2013 2 27 31.25249 37.76327

5 2013 3 8 85.86216 83.53692

6 2013 3 18 41.29189 30.11796

7 2013 4 10 38.41231 33.02368

8 2013 4 12 36.04814 34.83843

9 2013 4 18 36.02848 34.91536

10 2013 4 19 47.91170 46.12783

# ... with 39 more rows

其他数据源

和数据框一样,dplyr操作的数据可以可以用其它方式存储,像数据表(data tables)、数据库(databases)和多维矩阵(multidimensional arrays)等。

1)数据表

Dplyr还为所有的dplyr 中的verbs提供了data.table方法。如果你已经使用data.table,你可以使用dplyr语法进行数据操作以及data.table的其他任何事情。

对于多次操作,data.table可以变得更快,因为你通常可以同时使用多个verbs。例如,对data.table你可以在单步操作中同时使用mutate和select,它清楚知道对打算扔掉的行进行计算是很不明智的。

对data tables使用dplyr的好处:

(1)对于一般的数据操作工作,它将你从data.table的参考语义中隔离出来,并避免你意外修改数据。

(2)取代一个复杂的加下标操作符([)的方法,它提供了许多简单的方法。

2) 数据库(databases)

Dplyr同样允许你对一个远程数据库使用相同的verbs。 它负责为你生成SQL,这样你就不用频繁的切换语言。为了使用这些功能,你需要安装dplyr包,然后读取vignette(‘dplyr’)有关这些的详细情况。

3)多维矩阵/数据集(multidimensional array/cubes)

tbl_cube()为多维矩阵和多维数据集提供一个实验接口。如果你正在使用R中的数据形式,请联系我,这样我就可以更好地了解你的需求。

比较

与所有现有操作比较,dplyr:

1)将你的数据如何存储这个问题抽象化,所以你可以使用同一函数集对data frames、data tables、remote databases进行操作。这使得你只关注与你想获得什么,而不是关注后台的数据存储。

2)提供一个贴切的print()方法,不会向屏幕输出多页数据(这个灵感来自于data tables的输出)。

与基本函数(base functions)相比:

1)dplyr非常的一致,函数有相同的接口。所以一旦你精通一个,就可以很容易的学会其他函数。

2)基本函数是基于向量(vectors)的,而dplyr是基于数据框(data frames)的。

与plyr相比,dplyr:

1)更快

2)提供更好的外部集合连接思想

3)仅为数据框操作提供工具(例如多数dplyr等于ddply()+各种函数,do()等于dlply())

与事实上的数据框(data frame)方法相比:

1)它不会伪装你有一个数据框,如果你想运行lm等,你仍然需要手动下拉数据

2)它没有为R汇总函数(例如mean()或sum())提供方法

能力有限,翻译粗糙,仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值