R数据科学chapter3

library(nycflights13)

library(tidyverse)

#使用dplyr进行数据转换

#加载 tidyverse 时,仔细查看输出的冲突信息,

#它会告诉你 dplyr 覆盖了基础 R 包中的哪些 函数。

#如果想要在加载 dplyr 后使用这些函数的基础版本,

#那么你应该使用它们的完整名 称:stats::filter() 和 stats::lag()。

#nycflights13这个数据框包含了2013年从纽约市出发的所有336776次航班的信息。

flights

#只显示了前几行和适合屏幕宽度的几列。

#(要想看到整个数据集,可以使用 View(flights) 在 RStudio 查看器中打开数据集。)

View(flights)

#输出有差别是因为 flights 是一个 tibble。

#列名下面有一行 3 个或 4 个字母的缩写。它们描述了每个变量的类型。

#• int 表示整数型变量。

#• dbl 表示双精度浮点数型变量,或称实数。

#• chr 表示字符向量,或称字符串。

#• dttm 表示日期时间(日期 + 时间)型变量。

#• lgl 表示逻辑型变量,是一个仅包括 TRUE 和 FALSE 的向量。

#• fctr 表示因子,R 用其来表示具有固定数目的值的分类变量。

#• date 表示日期型变量。

#学习 5 个 dplyr 核心函数

#• 按值筛选观测(filter())。

#• 对行进行重新排序(arrange())。

#• 按名称选取变量(select())。

#• 使用现有变量的函数创建新变量(mutate())。

#• 将多个值总结为一个摘要统计量(summarize())。

#5 个函数的工作方式都是相同的。

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

#(2) 随后的参数使用变量名称(不带引号)描述了在数据框上进行的操作。

#(3) 输出结果是一个新数据框。

#filter() 函数可以基于观测的值筛选出一个观测子集。

#第一个参数是数据框名称,

#第二个参数以及随后的参数是用来筛选数据框的表达式。

#筛选出 1 月 1 日的所有航班

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

#dplyr 函数从来不修改输入,

#因此,如果想要保存函数结果,那么你就需要使用赋值操作符 <-

jan1 <- filter(flights, month == 1, day == 1)

#R 要么输出结果,要么将结果保存在一个变量中。

#如果想同时完成这两种操作,那么你可以用括号将赋值语句括起来

(jan1 <- filter(flights,month==1,day==1))

#R 提供了一套标准的比较运算符:>、>=、<、<=、!=(不等于)和 ==(等于)。

#易犯错误使用 = 而不是 == 来测试是否相等

filter(flights, month = 1)

#> Error: filter() takes unnamed arguments. Do you need `==`?

#使用 == 进行比较浮点数

sqrt(2) ^ 2 == 2

1/49 * 49 == 1

#计算机使用的是有限精度运算(显然无法存储无限位的数),

#因此请记住,你看到的每个 数都是一个近似值。

#比较浮点数是否相等时,不能使用 ==,而应该使用 near()

near(sqrt(2) ^ 2, 2)

near(1 / 49 * 49, 1)

#filter() 中的多个参数是由“与”组合起来的

#每个表达式都必须为真才能让一行观测包含在输出中。

#使用布尔运算符:& 表示“与”、| 表示 “或”、! 表示“非”

#找出 11 月或 12 月出发的所有航班

filter(flights, month == 11 | month == 12)

#不能写成filter(flights, month == 11 | 12) 这种形式

#代码中的含义是找出所有出发月份为 11 | 12 的航班。

#11 | 12 这个 逻辑表达式的值为 TRUE

#TRUE 就是 1,所以这段代码找出的不是11月或12月出发的航班,

#而是 1 月出发的所有航班。

#这种问题有一个有用的简写形式:x %in% y。

#这会选取出x是y中的一个值时的所有行。

nov_dec <- filter(flights, month %in% c(11, 12))

#德摩根定律将复杂的筛选条件进行简化

# !(x & y)等价于!x | !y

# !(x | y)等价于!x & !y

#延误时间(到达或出发)不多于2小时的航班

filter(flights, !(arr_delay > 120 | dep_delay > 120))

filter(flights, arr_delay <= 120, dep_delay <= 120)

#除 & 和 | 之外,R 中还有 && 和 || 运算符。

#先不要使用这两个运算符!

#只要 filter() 函数中使用的是复杂的、包含多个部分的表达式,

#就需要考虑用一个明确的 变量来代替它。

#这样检查代码会容易很多。

#缺失值,或称 NA(not available, 不可用)。

#NA 表示未知的值,因此缺失值是“可传染的”。

NA > 5

#> [1] NA

10 == NA

#> [1] NA

NA + 10

#> [1] NA

NA / 2

#> [1] NA

NA == NA

#> [1] NA

# 令x为Mary的年龄。我们不知道她有多大。

x <- NA

# 令y为John的年龄。我们不知道他有多大。

y <- NA

# John和Mary的年龄是相同的吗?

x == y

#> [1] NA

# 我们不知道!

#如果想要确定一个值是否为缺失值,可以使用 is.na() 函数:

is.na(x)

#> [1] TRUE

#filter() 只能筛选出条件为 TRUE 的行;

#它会排除那些条件为 FALSE 和 NA 的行。

#如果想保留缺失值,可以明确指出:

  df <- tibble(x = c(1, NA, 3))

  filter(df, x > 1)

  filter(df, is.na(x) | x > 1)

#到达时间延误 2 小时或更多的航班。

  filter(flights,arr_delay>=120)

#飞往休斯顿(IAH机场或HOU机场)的航班。

  filter(flights,dest=='IAH'|dest=='HOU')

  filter(flights,dest %in% c('IAH','HOU'))

#由联合航空(United)、美利坚航空(American)或三角洲航空(Delta)运营的航班。

  filter(flights,carrier %in% c('UA','AA','DL'))

#夏季(7月、8月和9月)出发的航班。

  filter(flights,month %in% c(7,8,9))

  filter(flights, month >= 7, month <= 9)

  filter(flights, between(month,7,9))

#到达时间延误超过 2 小时,但出发时间没有延误的航班。

  filter(flights,dep_delay<=0,arr_delay>120)

  filter(flights,!(dep_delay>0|arr_delay<=120))

#延误至少 1 小时,但飞行过程弥补回 30 分钟的航班。

  filter(flights, dep_delay >= 60, dep_delay - arr_delay > 30)

#出发时间在午夜和早上6点之间(包括0点和6点)的航班。

  filter(flights, dep_time<=600)

#dep_time 有缺失值的航班有多少? 

  filter(flights, is.na(dep_time))

  NA ^ 0

#[1] 1

  NA | TRUE

#[1] TRUE

  FALSE & NA

#[1] FALSE

  NA * 0

#[1] NA

#使用arrange()排列行

#arrange() 函数的工作方式与 filter() 函数非常相似,

#但前者不是选择行,而是改变行的顺序。

#它接受一个数据框和一组作为排序依据的列名(或者更复杂的表达式)作为参数。

#如果列名不只一个,那么就使用后面的列在前面排序的基础上继续排序:

  arrange(flights, year, month, day)

#使用 desc() 可以按列进行降序排序

  arrange(flights, desc(arr_delay))

#缺失值总是排在最后:

  df <- tibble(x = c(5, 2, NA))

  arrange(df, x)

  arrange(df, desc(x))

#如何使用 arrange() 将缺失值排在最前面?(提示:使用 is.na()。)

  arrange(df, desc(is.na(x)))

#对 flights 排序以找出延误时间最长的航班。找出出发时间最早的航班。

  arrange(flights,desc(arr_delay))

  arrange(flights,dep_time)

#对 flights 排序以找出速度最快的航班。

#哪个航班的飞行时间最长?哪个最短?

#使用select()选择列

#select() 函数可以让你快速生成一个有用的变量子集。

# 按名称选择列

  select(flights, year, month, day)

# 选择“year”和“day”之间的所有列(包括“year”和“day”)

  select(flights, year:day)

# 选择不在“year”和“day”之间的所有列(不包括“year”和“day”)

  select(flights, -(year:day))

#还可以在 select () 函数中使用一些辅助函数。

#  • starts_with("abc"):匹配以“abc”开头的名称。

#  • ends_with("xyz"):匹配以“xyz”结尾的名称。

#  • contains("ijk"):匹配包含“ijk”的名称。

#  • matches("(.)\\1"):选择匹配正则表达式的那些变量。

#  这个正则表达式会匹配名称中有重复字符的变量。

#  • num_range("x", 1:3):匹配 x1、x2 和 x3。

#select() 可以重命名变量,但我们很少这样使用它,

#因为这样会丢掉所有未明确提及的变 量。

#我们应该使用 select() 函数的变体 rename() 函数来重命名变量,以保留所有未明确 提及的变量:

  rename(flights, tail_num = tailnum)

#将 select() 函数和 everything() 辅助函数结合起来使用。

#当想要将几个变量移到数据框开头时,这种用法非常奏效:

  select(flights, time_hour, air_time, everything())

#从 flights 数据集中选择 dep_time、dep_delay、arr_time 和 arr_delay,通过头脑风暴找出尽可能多的方法。

  select(flights, starts_with("dep_"), starts_with("arr_"))

  select(flights,dep_time,dep_delay,arr_time,arr_delay)

#select忽略重复项,只选第一个。

    select(flights, year, month, day, year, year)

# one_of() 函数

    vars <- c(

      "year", "month", "day", "dep_delay", "arr_delay"

    )

    select(flights,one_of(vars))

#选择辅助函数处理大小写的默认方式忽略大小写

    select(flights, contains("TIME"))

# contains忽略了大小写,有个参数可以改变

    select(flights, contains("TIME", ignore.case = FALSE))

#使用mutate()添加新变量

#除了选择现有的列,我们还经常需要添加新列,新列是现有列的函数。

#这就是 mutate() 函数的作用。

#mutate() 总是将新列添加在数据集的最后,

#因此我们需要先创建一个更狭窄的数据集,以便能够看到新变量。

#当使用 RStudio 时,查看所有列的最简单的方法就是使用 View() 函数

    flights_sml <- select(flights,

                          year:day,

                          ends_with("delay"),

                          distance,

                          air_time

    )

    mutate(flights_sml,

          gain = arr_delay - dep_delay,

          speed = distance / air_time * 60

    )

#一旦创建,新列就可以立即使用

    mutate(flights_sml,

          gain = arr_delay - dep_delay,

          hours = air_time / 60,

          gain_per_hour = gain / hours

    )

#如果只想保留新变量,可以使用 transmute() 函数:

    transmute(flights,

              gain = arr_delay - dep_delay,

              hours = air_time / 60,

              gain_per_hour = gain / hours

    )   

#创建新变量的多种函数可供你同 mutate() 一同使用。

#最重要的一点是,这种函数必须是向量化的:

#它必须接受一个向量作为输入,并返回一个向量作为输出,

#而且输入向量与输出向量具有同样数目的分量。

#算术运算符:+、-、*、/、^

#当某个参数是单个数值时,这种方式是最有效的:

#    air_ time / 60、hours * 60 + minute 等。

#聚集函数

#x / sum(x)可以计算出各个分量在总数中的比例,

#y – mean(y)可以计算出分量与均值之间的差值

#模运算符:%/% 和 %%

#%/%(整数除法)和%%(求余)满足x == y * (x %/% y) + (x %% y)。

#模运算非常好用,因为它可以拆分整数。

#在航班数据集中,你可以根据 dep_time 计算出 hour 和 minute:

    transmute(flights,

              dep_time,

              hour = dep_time %/% 100,

              minute = dep_time %% 100

    )

#对数函数:log()、log2() 和 log10()

#在处理取值范围横跨多个数量级的数据时,对数是特别有用的一种转换方式。

#它还可以将乘法转换成加法。

#其他条件相同的情况下,推荐使用 log2() 函数,

#因为很容易对其进行解释:对数标度的数值增加 1 个单位,意味着初始数值加倍;

#减少1个单位,则意味着初始数值减半。   

#偏移函数

#lead() 和 lag() 函数可以返回一个序列的领先值和滞后值。

#它们可以计算出序列的移动差值(如x – lag(x))或发现序列何时发生了变化(x != lag(x))。

#它们与group_by() 组合使用时特别有用,你很快就会学到 group_by() 这个函数

    (x <- 1:10)

    #> [1] 1 2 3 4 5 6 7 8 9 10

    lag(x)

    #> [1] NA 1 2 3 4 5 6 7 8 9

    lead(x)

    #> [1] 2 3 4 5 6 7 8 9 10 NA

#累加和滚动聚合

#R 提供了计算累加和、累加积、累加最小值和累加最大值的函数:

#cumsum()、cumprod()、 commin() 和 cummax();

#dplyr 还提供了 cummean() 函数以计算累加均值。

#如果想要计算滚动聚合(即滚动窗口求和),那么可以尝试使用 RcppRoll 包:

    cumsum(x)

    #> [1] 1 3 6 10 15 21 28 36 45 55

    cummean(x)

    #> [1] 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5

#逻辑比较:<、<=、>、>= 和 !=

#    如果需要进行一系列复杂的逻辑运算,

#    那么最好将中间结果保存在新变量中,

#    这样就可以检查是否每一步都符合预期。

#排秩

#min_rank() 函数可以完成最常用的排秩任务 (如第一、第二、第三、第四)。

#默认的排秩方式是,最小的值获得最前面的名次,

#使用desc(x) 可以让最大的值获得最前面的名次

    y <- c(1, 2, 2, NA, 3, 4)

    min_rank(y)

    #> [1] 1 2 2 NA 4 5

    min_rank(desc(y))

    #> [1]  5  3  3 NA  2  1

#    min_rank() 无法满足需要,

#    那么可以看一下其变体 row_number()、dense_rank()、 percent_rank()、cume_dist() 和 ntile()

    row_number(y)

    #> [1] 1 2 3 NA 4 5

    dense_rank(y)

    #> [1] 1 2 2 NA 3 4

    percent_rank(y)

    #> [1] 0.00 0.25 0.25 NA 0.75 1.00

    cume_dist(y)

    #> [1] 0.2 0.6 0.6 NA 0.8 1.0

#使用summarize()进行分组摘要   

#它可以将数据框折叠成一行

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

    # A tibble: 1 × 1

    #> delay

    #>

    #> 1 12.6

#group_by() 可以将分析单位从整个数据集更改为单个分组。

#在分组后的数据框上使用 dplyr 函数时,它们会自动地应用到每个分组。

#group_by() 和 summarize() 的组合构成了使用 dplyr 包时最常用的操作之一

#分组摘要

#对按日期分组的一个数据框应用与上面完全相同的代码,

#那么我们就可以得到每日平均延误时间

by_day <- group_by(flights, year, month, day)

summarize(by_day, delay = mean(dep_delay, na.rm = TRUE))

#介绍一个功能强大的新概念:管道

#研究每个目的地的距离和平均延误时间之间的关系

#完成数据准备需要 3 步。

#(1) 按照目的地对航班进行分组。

by_dest <- group_by(flights, dest)

#(2) 进行摘要统计,计算距离、平均延误时间和航班数量。

delay <- summarize(by_dest,

                  count = n(),

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

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

)

#(3) 通过筛选除去噪声点和火奴鲁鲁机场,因为到达该机场的距离几乎是到离它最近机场的距离的 2 倍。

delay <- filter(delay, count > 20, dest != "HNL")

#这段代码写起来有点令人泄气,因为不得不对每个中间数据框命名,尽管我们根本不关心这一点。

#命名是很难的,这样做会影响我们的分析速度。

#解决这个问题的另一种方法是使用管道,%>%

delays <- flights %>%

  group_by(dest) %>%

  summarize(

    count = n(),

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

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

  ) %>%

  filter(count > 20, dest != "HNL")

#这种方法的重点在于转换的过程,而不是转换的对象,

#这使得代码具有更好的可读性。

#你可以将其读作一串命令式语句:分组,然后摘要统计,然后进行筛选。

#在阅读代码时,%>% 最好读作“然后”。

#使用这种方法时,x %>% f(y)会转换为f(x, y),

#x %>% f(y) %>% g(z)会转换为g(f(x, y), z),以此类推。

#支持管道操作是 tidyverse 中的 R 包的核心原则之一。

#唯一的例外就是 ggplot2:它是在发 现管道方式前开发的。

#ggplot2 的下一个版本 ggvis 支持管道操作,遗憾的是其还没有达到成熟完备的程度。

#缺失值

#如果输入中有缺失值,那么输出也会是缺失值。

#所有聚合函数都有一个 na.rm 参数,它可以在计算前除去缺失值

#缺失值表示取消的航班,

flights %>%

group_by(year, month, day) %>%

  summarize(mean = mean(dep_delay, na.rm = TRUE))

#我们也可以通过先去除取消的航班来解决缺失值问题。

not_cancelled <- flights %>%

  filter(!is.na(dep_delay), !is.na(arr_delay))

not_cancelled %>%

  group_by(year, month, day) %>%

  summarize(mean = mean(dep_delay))

#计数

#聚合操作中包括一个计数(n())或非缺失值的计数(sum(!is_na()))

#确保自己没有基于非常少量的数据作出结论

#具有最长平均延误时间的飞机(通过机尾编号进行识别)

delays <- not_cancelled %>%

  group_by(tailnum) %>%

  summarize(

    delay = mean(arr_delay)

  )

ggplot(data = delays, mapping = aes(x = delay)) +

  geom_freqpoly(binwidth = 10)

#画一张航班数量和平均延误时间的散点图

delays <- not_cancelled %>%

  group_by(tailnum) %>%

  summarize(

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

    n = n() )

ggplot(data = delays, mapping = aes(x = n, y = delay)) +

  geom_point(alpha = 1/10)

#当航班数量非常少时,平均延误时间的变动特别大。

#这张图的形状非常能够说明问题:

#当绘制均值(或其他摘要统计量)和分组规模的关系时,

#你总能看到随着样本量的增加,变动在不断减小。

#通常应该筛选掉那些观测数量非常少的分组,

#这样你就可以避免受到特别小的分组中的极端变动的影响,

#进而更好地发现数据模式。

#展示了将 ggplot2 集成到 dplyr 工作流中的一种有效方式。

#从 %>% 过渡到 + 会令人感到不适应,但掌握其中的要领后,这种写法是非常方便的:

delays %>%

  filter(n > 25) %>%

  ggplot(mapping = aes(x = n, y = delay)) +

  geom_point(alpha = 1/10)

#棒球击球手的平均表现与击球次数之间的关系。

#击球手的能力(用打击率 ba 衡量)与击球机会数量(用打数 ab 衡量)

batting <- as_tibble(Lahman::Batting) # 转换成tibble,以便输出更美观

batters <- batting %>%

  group_by(playerID) %>%

  summarize(

    ba = sum(H, na.rm = TRUE) / sum(AB, na.rm = TRUE),

    ab = sum(AB, na.rm = TRUE) )

batters %>%

  filter(ab > 100) %>%

  ggplot(mapping = aes(x = ab, y = ba)) +

  geom_point() +

  geom_smooth(se = FALSE)

#> `geom_smooth()` using method = 'gam'

#常用的摘要函数

#只使用均值、计数和求和是远远不够的

#位置度量

#我们已经使用过 mean(x),但 median(x) 也非常有用。

#均值是总数除以个数;

#中位数则 是这样一个值:50% 的 x 大于它,同时 50% 的 x 小于它。

#有时候需要将聚合函数和逻辑筛选组合起来使用。

not_cancelled %>%

  group_by(year, month, day) %>%

  summarize(

    # 平均延误时间:

    avg_delay1 = mean(arr_delay),

    # 平均正延误时间:

    avg_delay2 = mean(arr_delay[arr_delay > 0])

  )

#分散程度度量:sd(x)、IQR(x) 和 mad(x)

#均方误差(又称标准误差,standard deviation,sd)是分散程度的标准度量方式。

#四分位距 IQR() 和绝对中位差 mad(x) 基本等价,更适合有离群点的情况:

# 为什么到某些目的地的距离比到其他目的地更多变?

not_cancelled %>%

group_by(dest) %>%

  summarize(distance_sd = sd(distance)) %>%

  arrange(desc(distance_sd))

#秩的度量:min(x)、quantile(x, 0.25) 和 max(x)

#分位数是中位数的扩展。

#例如,quantile(x, 0.25)会找出x中按从小到大顺序大于前 25% 而小于后75% 的值:

# 每天最早和最晚的航班何时出发?

not_cancelled %>%

group_by(year, month, day) %>%

  summarize(

    first = min(dep_time),

    last = max(dep_time)

  )

#定位度量:first(x)、nth(x, 2) 和 last(x)

#这几个函数的作用与 x[1]、x[2] 和 x[length(x)] 相同,

#只是当定位不存在时(比如尝试从只有两个元素的分组中得到第三个元素),

#前者允许你设置一个默认值。

#例如,我们可以找出每天最早和最晚出发的航班:

not_cancelled %>%

  group_by(year, month, day) %>%

  summarize(

    first_dep = first(dep_time),

    last_dep = last(dep_time)

  )

#这些函数对筛选操作进行了排秩方面的补充。

#筛选会返回所有变量,每个观测在单独的一行中:

not_cancelled %>%

  group_by(year, month, day) %>%

  mutate(r = min_rank(desc(dep_time))) %>%

  filter(r %in% range(r))

#range()返回的是一个向量里面最大值和最小值

#计数

#你已经见过 n(),它不需要任何参数,并返回当前分组的大小。

#计算出非缺失值的数量,可以使用 sum(!is.na(x))。

#要想计算出唯一值的数量,可以使用 n_ distinct(x)

# 哪个目的地具有最多的航空公司?

not_cancelled %>%

group_by(dest) %>%

  summarize(carriers = n_distinct(carrier)) %>%

  arrange(desc(carriers))

#dplyr 提供了一个简单的辅助函数,用于只需要计数的情况:

not_cancelled %>%

  count(dest)

#还可以选择提供一个加权变量。

#例如,你可以使用以下代码算出每架飞机飞行的总里程数(实际上就是求和)

not_cancelled %>%

  count(tailnum, wt = distance)

#逻辑值的计数和比例:sum(x > 10) 和 mean(y == 0)

#当与数值型函数一同使用时,TRUE 会转换为 1,FALSE 会转换为 0。

#这使得 sum() 和 mean() 非常适用于逻辑值:

#sum(x) 可以找出 x 中 TRUE 的数量,mean(x) 则可以找出比例。

# 多少架航班是在早上5点前出发的?(这通常表明前一天延误的航班数量)

not_cancelled %>%

group_by(year, month, day) %>%

  summarize(n_early = sum(dep_time < 500))

# 延误超过1小时的航班比例是多少?

not_cancelled %>%

group_by(year, month, day) %>%

  summarize(hour_perc = mean(arr_delay > 60))

#按多个变量分组

#当使用多个变量进行分组时,每次的摘要统计会用掉一个分组变量。

daily <- group_by(flights, year, month, day)

(per_day <- summarize(daily, flights = n()))

(per_month <- summarize(per_day, flights = sum(flights)))

(per_year <- summarize(per_month, flights = sum(flights)))

#在循序渐进地进行摘要分析时,需要小心:使用求和与计数操作是没问题的,

#但如果想要 使用加权平均和方差的话,就要仔细考虑一下,

#在基于秩的统计数据(如中位数)上是无法进行这些操作的。

#换句话说,对分组求和的结果再求和就是对整体求和,

#但分组中位数的中位数可不是整体的中位数。

#取消分组

#如果想要取消分组,并回到未分组的数据继续操作,

#那么可以使用 ungroup() 函数:

daily %>%

  ungroup() %>% # 不再按日期分组

  summarize(flights = n()) # 所有航班

#这些函数都可以和 group_by() 函数联合起来使用,

#group_by() 函数可以改变以上每个函数的作用范围,

#让其从在整个数据集上操作变为在每个分组上分别操作。

#一架航班 50% 的时间会提前 15 分钟,50% 的时间会延误 15 分钟。

not_cancelled %>%

group_by(tailnum) %>%

summarise(delay_perc1=mean(dep_delay==-15),delay_perc2=mean(arr_delay==-15))%>%

  filter(delay_perc1==0.5,delay_perc2==0.5)

#分组新变量(和筛选器)

#虽然与 summarize() 函数结合起来使用是最有效的,

#但分组也可以与 mutate() 和 filter()函数结合,以完成非常便捷的操作。

#找出每个分组中最差的成员:

flights_sml %>%

  group_by(year, month, day) %>%

  filter(rank(desc(arr_delay)) < 10)

#找出大于某个阈值的所有分组:

  popular_dests <- flights %>%

  group_by(dest) %>%

  filter(n() > 365)

popular_dests

#对数据进行标准化以计算分组指标:

popular_dests %>%

  filter(arr_delay > 0) %>%

  mutate(prop_delay = arr_delay / sum(arr_delay)) %>%

  select(year:day, dest, arr_delay, prop_delay)

你可能感兴趣的:(R数据科学chapter3)