前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >R数据科学|3.7内容介绍及习题解答

R数据科学|3.7内容介绍及习题解答

作者头像
庄闪闪
发布2021-04-09 11:08:43
3.7K0
发布2021-04-09 11:08:43
举报

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

虽然与summarize()函数结合起来使用是最有效的,但分组也可以与mutate()filter()函数结合,以完成非常便捷的操作。示例如下:

  • 找出每个分组中最差的成员:
代码语言:javascript
复制
flights_sml %>%
 group_by(year, month, day) %>%
 filter(rank(desc(arr_delay)) < 10)
#> Source: local data frame [3,306 x 7]
#> Groups: year, month, day [365]
#>
#> year month day dep_delay arr_delay distance
#> <int> <int> <int> <dbl> <dbl> <dbl>
#> 1 2013 1 1 853 851 184
#> 2 2013 1 1 290 338 1134
#> 3 2013 1 1 260 263 266
#> 4 2013 1 1 157 174 213
#> 5 2013 1 1 216 222 708
#> 6 2013 1 1 255 250 589
#> # ... with 3,300 more rows, and 1 more variables:
#> # air_time <dbl>
  • 找出大于某个阈值的所有分组:
代码语言:javascript
复制
popular_dests <- flights %>%
 group_by(dest) %>%
 filter(n() > 365)
popular_dests
#> Source: local data frame [332,577 x 19]
#> Groups: dest [77]
#>
#> year month day dep_time sched_dep_time dep_delay
#> <int> <int> <int> <int> <int> <dbl>
#> 1 2013 1 1 517 515 2
#> 2 2013 1 1 533 529 4
#> 3 2013 1 1 542 540 2
#> 4 2013 1 1 544 545 -1
#> 5 2013 1 1 554 600 -6
#> 6 2013 1 1 554 558 -4
#> # ... with 3.326e+05 more rows, and 13 more variables:
#> # arr_time <int>, sched_arr_time <int>,
#> # arr_delay <dbl>, carrier <chr>, flight <int>,
#> # tailnum <chr>, origin <chr>, dest <chr>,
#> # air_time <dbl>, distance <dbl>, hour <dbl>,
#> # minute <dbl>, time_hour <dttm>
  • 对数据进行标准化以计算分组指标:
代码语言:javascript
复制
popular_dests %>%
 filter(arr_delay > 0) %>%
 mutate(prop_delay = arr_delay / sum(arr_delay)) %>%
 select(year:day, dest, arr_delay, prop_delay)
#> Source: local data frame [131,106 x 6]
#> Groups: dest [77]
#>
#> year month day dest arr_delay prop_delay
#> <int> <int> <int> <chr> <dbl> <dbl>
#> 1 2013 1 1 IAH 11 1.11e-04
#> 2 2013 1 1 IAH 20 2.01e-04
#> 3 2013 1 1 MIA 33 2.35e-04
#> 4 2013 1 1 ORD 12 4.24e-05
#> 5 2013 1 1 FLL 19 9.38e-05
#> 6 2013 1 1 ORD 8 2.83e-05
#> # ... with 1.311e+05 more rows

【注】:分组筛选器的作用相当于分组新变量加上未分组筛选器。一般不使用分组筛选器,除非是为了完成快速、粗略的数据处理,否则很难检查数据处理的结果是否正确。

在分组新变量和筛选器中最常使用的函数称为窗口函数(与用于统计的摘要函数相对)。你可以在相应的使用指南中学习到更多关于窗口函数的知识:vignette("windowfunctions")

习题解答

问题一

查看常用的新变量函数和筛选函数的列表。当它们与分组操作结合使用时,功能有哪些变化?

解答

  • 受影响的有: mean(), lead(), lag(), min_rank(), row_number(), mean(), sum(), sd()
代码语言:javascript
复制
tibble(x = 1:9,
       group = rep(c("a", "b", "c"), each = 3)) %>%
  mutate(x_mean = mean(x)) %>%
  group_by(group) %>%
  mutate(x_mean_2 = mean(x))
#> # A tibble: 9 x 4
#> # Groups:   group [3]
#>       x group x_mean x_mean_2
#>   <int> <chr>  <dbl>    <dbl>
#> 1     1 a          5        2
#> 2     2 a          5        2
#> 3     3 a          5        2
#> 4     4 b          5        5
#> 5     5 b          5        5
#> 6     6 b          5        5
#> # … with 3 more rows
  • 不受影响的有: 运算符(+,-,<,==,%%,%/%)
代码语言:javascript
复制
tibble(x = 1:9,
       group = rep(c("a", "b", "c"), each = 3)) %>%
  mutate(y = x + 2) %>%
  group_by(group) %>%
  mutate(z = x + 2)
#> # A tibble: 9 x 4
#> # Groups:   group [3]
#>       x group     y     z
#>   <int> <chr> <dbl> <dbl>
#> 1     1 a         3     3
#> 2     2 a         4     4
#> 3     3 a         5     5
#> 4     4 b         6     6
#> 5     5 b         7     7
#> 6     6 b         8     8
#> # … with 3 more rows

问题二

哪一架飞机(用机尾编号来识别,tailnum)具有最差的准点记录?

解答

我筛选至少飞行了20次的飞机。选择20是因为它是接近飞机飞行次数的上四分位数。

代码语言:javascript
复制
quantile(count(flights, tailnum)$n)
#>   0%  25%  50%  75% 100% 
#>    1   23   54  110 2512

将平均延误时间作为衡量标准。

代码语言:javascript
复制
flights %>%
  filter(!is.na(arr_delay)) %>%
  group_by(tailnum) %>%
  summarise(arr_delay = mean(arr_delay), n = n()) %>%
  filter(n >= 20) %>%
  filter(min_rank(desc(arr_delay)) == 1)
#> `summarise()` ungrouping output (override with `.groups` argument)
#> # A tibble: 1 x 3
#>   tailnum arr_delay     n
#>   <chr>       <dbl> <int>
#> 1 N203FR       59.1    41

问题三

如果想要尽量避免航班延误,那么应该在一天中的哪个时间搭乘飞机?

解答

可以按飞行时间分组,航班预定的时间越早,预计延误的时间就越低,因为延误会影响之后的航班。比如,早上的航班不容易受延误影响,是因为它们之前的航班较少。

代码语言:javascript
复制
flights %>%
  group_by(hour) %>%
  summarise(arr_delay = mean(arr_delay, na.rm = TRUE)) %>%
  arrange(arr_delay)
#> `summarise()` ungrouping output (override with `.groups` argument)
#> # A tibble: 20 x 2
#>    hour arr_delay
#>   <dbl>     <dbl>
#> 1     7    -5.30 
#> 2     5    -4.80 
#> 3     6    -3.38 
#> 4     9    -1.45 
#> 5     8    -1.11 
#> 6    10     0.954
#> # … with 14 more rows

问题四

计算每个目的地的延误总时间的分钟数,以及每架航班到每个目的地的延误时间比例。

解答

代码语言:javascript
复制
#每个目的地的延误总时间的分钟数
flights %>%
  filter(arr_delay > 0) %>%
  group_by(dest) %>%
  mutate(
    arr_delay_total = sum(arr_delay),
    arr_delay_prop = arr_delay / arr_delay_total
  ) %>%
  select(dest, month, day, dep_time, carrier, flight,
         arr_delay, arr_delay_prop) %>%
  arrange(dest, desc(arr_delay_prop))
代码语言:javascript
复制
#每架航班到每个目的地的延误时间比例
flights %>%
  filter(arr_delay > 0) %>%
  group_by(dest, origin, carrier, flight) %>%
  summarise(arr_delay = sum(arr_delay)) %>%
  group_by(dest) %>%
  mutate(
    arr_delay_prop = arr_delay / sum(arr_delay)
  ) %>%
  arrange(dest, desc(arr_delay_prop)) %>%
  select(carrier, flight, origin, dest, arr_delay_prop)

问题五

延误通常是由临时原因造成的:即使最初引起延误的问题已经解决,但因为要让前面的航班先起飞,所以后面的航班也会延误。使用 lag() 函数探究一架航班延误与前一架航班延误之间的关系。

解答

代码语言:javascript
复制
#计算同一机场前一航班的起飞延误。
lagged_delays <- flights %>%
 arrange(origin, month, day, dep_time) %>%
 group_by(origin) %>%
 mutate(dep_delay_lag = lag(dep_delay)) %>%
 filter(!is.na(dep_delay), !is.na(dep_delay_lag))

下面绘制了前一航班所有值与平均延误之间的关系。对于延误小于两小时的航班,前一航班的延误与当前航班的延误关系接近一条直线。在这之后,这种关系变得更加多变,因为长时间延误的航班与准时起飞的航班穿插在一起。大约8个小时后,一个航班延误之后可能会有一个航班准时起飞。

代码语言:javascript
复制
lagged_delays %>%
  group_by(dep_delay_lag) %>%
  summarise(dep_delay_mean = mean(dep_delay)) %>%
  ggplot(aes(y = dep_delay_mean, x = dep_delay_lag)) +
  geom_point() +
  scale_x_continuous(breaks = seq(0, 1500, by = 120)) +
  labs(y = "Departure Delay", x = "Previous Departure Delay")

问题六

查看每个目的地。你能否发现有些航班的速度快得可疑?(也就是说,这些航班的数据可能是错误的。)计算出到目的地的最短航线的飞行时间。哪架航班在空中的延误时间最长?

解答

先对数据进行标准化处理

代码语言:javascript
复制
standardized_flights <- flights %>%
  filter(!is.na(air_time)) %>%
  group_by(dest, origin) %>%
  mutate(
    air_time_mean = mean(air_time),
    air_time_sd = sd(air_time),
    n = n()
  ) %>%
  ungroup() %>%
  #加1是为了避免分母为0
  mutate(air_time_standard = (air_time - air_time_mean) / (air_time_sd + 1))

查看标准化后的航班分布

代码语言:javascript
复制
standardized_flights %>%
  arrange(air_time_standard) %>%
  select(
    carrier, flight, origin, dest, month, day,
    air_time, air_time_mean, air_time_standard
  ) %>%
  head(10) %>%
  print(width = Inf)

计算出到目的地的最短航线的飞行时间

代码语言:javascript
复制
flights %>%
 mutate(mph = distance / (air_time / 60)) %>%
 arrange(desc(mph)) %>%
 select(
   origin, dest, mph, year, month, day, dep_time, flight, carrier,
   dep_delay, arr_delay
 )

寻找在空中的延误时间最长的航班

代码语言:javascript
复制
air_time_delayed <-
 flights %>%
 group_by(origin, dest) %>%
 mutate(
   air_time_min = min(air_time, na.rm = TRUE),
   air_time_delay = air_time - air_time_min,
   air_time_delay_pct = air_time_delay / air_time_min * 100
 )
  arrange(desc(air_time_delay)) %>%
 select(
   air_time_delay, carrier, flight,
   origin, dest, year, month, day, dep_time,
   air_time, air_time_min
 ) %>%
 head() %>%
 print(width = Inf)

问题七

找出至少有两个航空公司的所有目的地。使用数据集中的信息对航空公司进行排名。

解答

计算这个排名有两个步骤。首先,找出有两家或两家以上航空公司服务的所有机场。然后,根据运营商服务的目的地数量对它们进行排名。

代码语言:javascript
复制
flights %>%
   # 找出有两家或两家以上航空公司服务的所有机场
   group_by(dest) %>%
   mutate(n_carriers = n_distinct(carrier)) %>%
   filter(n_carriers > 1) %>%
   # 根据运营商服务的目的地数量对它们进行排名
   group_by(carrier) %>%
   summarize(n_dest = n_distinct(dest)) %>%
   arrange(desc(n_dest))
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-12-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 庄闪闪的R语言手册 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 3.7 分组新变量(和筛选器)
  • 习题解答
    • 问题一
      • 解答
    • 问题二
      • 解答
    • 问题三
      • 解答
    • 问题四
      • 解答
    • 问题五
      • 解答
    • 问题六
      • 解答
    • 问题七
      • 解答
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档