dplyr包官方文档翻译


dplyr包可以让以下操作步骤变得简单,如:
它提供了一些操作类型的“动词”、函数,适用于大多数情况的数据操作,帮助你用代码实现你的想法。
通过限定一些指定的条件,可以构思非常复杂的数据操作。
后台运算效率很高,等待计算的时间也比较少。
本文档只介绍data.frame的操作。dplyr包也可以对数据库进行操作,可以通过dbplyr包学习

使用的数据: nycflights13

install.packages("nycflights13")
library(nycflights13)
dim(flights)
flights

注:tibble是R内置的传统数据框 tibble:简单数据框,用tidyverse中的tibble包实现

1. 最基本的函数

dplyr 对每一个基本操作(上述的“动词”)提供了一个函数:
1.1 filter() 函数可以用于筛选数据
1.2 arrange() 函数可以对数据进行排序
1.3 select() 和 rename() 可以选择变量
1.4 mutate() 和 transmute() 可以添加变量
1.5 summarise() 可以把多个值汇总成一个值
1.6 sample_n() 和 sample_frac() 可以用于随机抽样。

library(dplyr)
# 1.1 filter()函数
# For example, we can select all flights on January 1st with:
filter(flights, month == 1, day == 1)

# 如果用基础R语法,以上大概是的这样操作:
flights[flights$month == 1 & flights$day == 1, ]

# 可以大致比较下二者的耗时
system.time(filter(flights, month == 1, day == 1))
system.time(flights[flights$month == 1 & flights$day == 1, ])
# 会发现前者速度更快

# 1.2 arrange()函数
# arrange() 和 filter()函数类似,不过是用于数据排序,是对一个数据框或一个字段名的集合(或更复杂的数据集)进行排序。对多个列使用时,每个列都会进行排序。
arrange(flights, year, month, day)

# 使用 desc() 进行降序排列
arrange(flights, desc(arr_delay))

# 1.3 select()函数
# 选择列,迅速构造子集
# Select columns by name
select(flights, year, month, day)

# Select all columns between year and day (inclusive)
select(flights, year:day)

# Select all columns except those from year to day (inclusive)
select(flights, -(year:day))

# 还有很多配合 select()使用的函数, 例如 starts_with(), ends_with(), matches() 和 contains(). 这些可以让你迅速进行查找和匹配. 使用 ?select 查看详情。

# select() 还可以对变量进行重命名:
select(flights, tail_num = tailnum)

# 但这种重命名方法会导致无法获取到那些没有明确指定的变量,所以就没那么实用,我们用rename()函数来代替它
rename(flights, tail_num = tailnum)

# 1.4 使用mutate()函数
# 除了选择数据集现有的列,我们经常需要对数据集添加新的列,这时需要使用 mutate():
mutate(flights,
       gain = arr_delay - dep_delay,
       speed = distance / air_time * 60
)

# dplyr::mutate() 和 base 包 transform() 函数很相似,但它允许调用刚才新增的列:
mutate(flights,
       gain = arr_delay - dep_delay,
       gain_per_hour = gain / (air_time / 60)
)

# 如果你想只显示新增的列,可以使用 transmute()函数
transmute(flights,
          gain = arr_delay - dep_delay,
          gain_per_hour = gain / (air_time / 60)
)

# 1.5 使用 summarise() 函数对数据进行汇总
summarise(flights,
          delay = mean(dep_delay, na.rm = TRUE)
)
# 不过后面我们学习group_by(),就很少使用summarise()函数了。

# 1.6 使用sample_n() 和 sample_frac() 进行随机抽样:
# use sample_n()的参数是一个具体数值, sample_frac()的参数是一个百分数。

sample_n(flights, 10)
sample_frac(flights, 0.01)

# 可以使用 replace = TRUE 来修改抽样是否放回。更多参数见 ?sample_n

小结

我们会发现上述函数和操作都有一些共同点:
1)第一个参数是data frame
2)剩下的参数都是根据你对data frame 的操作来选择使用的。我们可以直接引用data frame的列,无须使用 $ 符号
3)生成的结果还是一个 data frame,灵活使用上述函数后,我们可以完成一系列简单操作,抽取更复杂的数据集
4)这5个函数提供了数据操作的基本语法。通常情况下,我们只需要对一个整洁数据框进行如下5种操作:排序(arrange),选择变量(filter和select),增加变量(mutate),或者聚合值(summarise)。剩下的内容中,作者会告诉我们如何对以上5种操作进行混合使用,处理数据的分组。

2. 分组(Grouped)操作

dplyr的操作“动词”可以根据他们实现的功能来分类,其中比较重要的分类就是分组(grouped)及其反向操作(ungrouped)。
Grouped 操作
将dplyr的操作动词应用于成组的数据时,会凸显它的强大。在dplyr中,可以使用group_by()函数进行操作。它将数据集分解为指定的行组,当你将上面的动词应用到结果集时,它们将自动“按组”应用。
分组对动词的影响如下:
1)grouped select() 和 ungrouped select() 相同,除非 grouping 的变量需要一直保留。
2)grouped arrange() 和 ungrouped 相同,除非设置了 .by_group = TRUE,这种情况下它会先对分组变量进行排序。
3)mutate() 和 filter() 与窗口函数(“window-functions”)结合起来非常有用,如rank(), 或 min(x) == x,在 “window-functions” 中有详细描述。
4)sample_n() 和 sample_frac() 可以对每个组中进行抽样(按样本数或抽样的百分比)
5)summarise() 计算每个分组的汇总数据。

# 接下来,我们把完整的数据集按飞机进行分组切割,然后对分割后的数据集进行计(count = n())、求距离的平均值(dist = mean(distance, na.rm = TRUE))、求晚点的平均值(delay = mean(arr_delay, na.rm = TRUE)),然后用ggplot2进行可视化。
by_tailnum <- group_by(flights, tailnum)
delay <- summarise(by_tailnum,
                   count = n(),
                   dist = mean(distance, na.rm = TRUE),
                   delay = mean(arr_delay, na.rm = TRUE))
delay <- filter(delay, count > 20, dist < 2000)

# 有意思的是,对每架飞机而言,平均晚点时间(average delay)和平均距离(average distance)只是弱相关的
library(ggplot2)
ggplot(delay, aes(dist, delay)) +
    geom_point(aes(size = count), alpha = 1/2) +
    geom_smooth() +
    scale_size_area()
# 笔记:这种复杂的操作可以用dplyr和管道操作符 %>% 结合使用,语法会显得更优雅,例如。管道操作符见第7点的说明。
flights %>%
    group_by(tailnum) %>%
    summarise(count = n(),
              dist = mean(distance, na.rm = TRUE),
              delay = mean(arr_delay, na.rm = TRUE)) %>%
    filter(count > 20, dist < 2000) %>%
    ggplot(aes(dist, delay)) +
    geom_point(aes(size = count), alpha = 1/2) +
    geom_smooth() +
    scale_size_area()

# 我们将summarise()和聚合函数结合起来使用,可以根据输入的向量返回一个数值。在base包里,有很多这样的函数可供使用,例如 min(), max(), mean(), sum(), sd(), median() 和 IQR()。除此以外,dplyr还提供了很多其他的函数:
# 1)n(): 当前分组的观测值的个数(即行数)
# 2)n_distinct(x): x 里的唯一值的个数
# 3)first(x), last(x) 和 nth(x, n),这些函数就像 x[1], x[length(x)], x[n] 一样,而且返回值如果为空的话,我们可以加更多控制条件。

# 例如,我们可以用这些函数找到去任意一个目的地的飞机数和航班数
destinations <- group_by(flights, dest)
summarise(destinations,
          planes = n_distinct(tailnum),
          flights = n()
)

# 按多列进行group_by 时,每次汇总都会剥离掉一个 level。
daily <- group_by(flights, year, month, day)
(per_day   <- summarise(daily, flights = n()))
(per_month <- summarise(per_day, flights = sum(flights)))
(per_year  <- summarise(per_month, flights = sum(flights)))

3. select 操作

dplyr包的select操作可以像引用正则变量一样。

# `year` represents the integer 1
select(flights, year)
select(flights, 1)

# 如果周围上下文中的变量与列之一具有相同的名称,则不能引用它们,如
year <- 5
select(flights, year)

# 但这样引用却可以
year <- "dep"
select(flights, starts_with(year))

# 要引用数值变量所指的列,可以这样使用
year <- 5
select(flights, year, identity(year))

# 也可以是多个列名拼接的字符串
vars <- c("year", "month")
select(flights, vars, "day") # 与 select(flights, vars, day) 相同

# 注意,上面的代码有些不安全,因为我们可能已经往tibble添加了一个名为vars的列。为了避免这个问题,可以将变量包装在放在标识符中调用,如使用 “!!” 操作符,这可以让dplyr直接查看上下文:
# Let's create a new `vars` column:
flights$vars <- flights$year

# 如果使用 `!!` 操作符这不会新增列:
vars <- c("year", "month", "day")
select(flights, !! vars)

4. Mutating 操作

# 先创建一个小的 tibble
df <- select(flights, year:dep_time)

# 使用select()和mutate()引用时存在一些区别,例如使用bare column names:
select(df, "year")
mutate(df, "year")
# 如果mutate(., 数值),也会当做一个新的列
mutate(df, "year", 2)
# 如果想mutate()一个值为year,名为a的列,应该如下操作:
mutate(df, a = 'year')

# 注:以上来看,mutate()中的参数更像是引用一个对象,而非具体的值(当参数是具体的值时,会对该值处理为对象),下面还会印证我的理解。
mutate(df, year + 10)

var <- seq(1, nrow(df))
mutate(df, new = var)

5. group_by()

# 可以对修改的列使用
group_by(df, month)
group_by(df, month = as.factor(month))
group_by(df, day_binned = cut(day, 3))

6. _at()

# dplyr中,以_at()为后缀的变量可以用于选择变量,但需要用vars()包起来。可以查看帮助文档。
group_by_at(df, vars(year:day))
select_at(df, vars(year))

7. 管道操作符

# 当条件变得复杂时,可以使用管道操作符,这样语法可以变得简洁:
# 如,我们想完成以下数据的操作:
a1 <- group_by(flights, year, month, day)
a2 <- select(a1, arr_delay, dep_delay)
a3 <- summarise(a2,
                arr = mean(arr_delay, na.rm = TRUE),
                dep = mean(dep_delay, na.rm = TRUE))
a4 <- filter(a3, arr > 30 | 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
)

# 但很明显,代码的可读性变得很差了。在此,我们引入管道操作符,语法格式如下:
# x %>% f(y) 表示 f(x,y)
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)

8. data table

dplyr不仅可以对data frames 使用,还可以对 data table、database、multidimensional arrays/cube 使用。
对 database 使用可以阅读 dbplyr 的说明文档;
对 multidimensional arrays/cube 的使用可以使用 tbl_cube 函数

总结

相比base包的函数,dplyr包的函数显得更加连贯。base包的函数更多趋向于对向量使用,而dplyr更多趋向于对data frame使用。
相比 plyr, dplyr的速度更快

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值