我目前正在研究R for Data Science,尤其是练习5.7.1 #8,它正在分析library(nycflights13)
数据包数据。
问题如下:
- 对于每架飞机,计算第一次延迟超过1小时之前的飞行次数。
我的尝试是通过使用first()
函数创建一个表来查找第一个“超过60分钟”的延迟:
first_del <- flights %>%
select(month, day, flight, dep_time, tailnum, dep_delay) %>%
filter(dep_delay > 60) %>%
group_by(month,day) %>%
arrange(month, day, dep_time) %>%
summarise(flight = first(flight), first_time = first(dep_time))
first_del
# A tibble: 365 x 4
# Groups: month [?]
month day flight first_time
<int> <int> <int> <int>
1 1 1 4576 811
2 1 2 22 126
3 1 3 104 50
4 1 4 608 106
5 1 5 11 37
6 1 6 27 746
7 1 7 145 756
8 1 8 4334 740
9 1 9 51 641
10 1 10 905 743
# ... with 355 more rows
我的想法是,如果flights
标题1中的每一行与月,日匹配,并且小于当天的第一次延误航班的航班号(例如,从{ {1}}稍作调整,航班4576是1月1日的首个“超过60分钟的延迟”航班,在此之前的所有其他航班都将计算在内)。所需的输出将类似于:
first_del
理想情况下,每天根据 flights %>%
filter(dep_time > 805) %>%
select(month, day, flight, dep_time, tag)
# A tibble: 272,933 x 4
month day flight dep_time tag
<int> <int> <int> <int> <int>
1 1 1 269 807 1
2 1 1 4388 809 1
3 1 1 3538 810 1
4 1 1 2395 810 1
5 1 1 4260 811 1
6 1 1 4576 811 1
7 1 1 675 811 0
8 1 1 4537 812 0
9 1 1 914 813 0
10 1 1 346 814 0
小标题对所有行数小于或等于航班号的行进行计数会很棒。我尝试使用过滤器的许多组合,%in%,突变,但尚未成功。我应该创建一个自定义函数吗?
我最终想要的输出是(具有虚拟 first_del
值):
$count
其中 first_del
# A tibble: 365 x 4
# Groups: month [?]
month day flight first_time count
<int> <int> <int> <int> <int>
1 1 1 4576 811 212
2 1 2 22 126 216
3 1 3 104 50 298
4 1 4 608 106 220
5 1 5 11 37 168
6 1 6 27 746 287
7 1 7 145 756 302
8 1 8 4334 740 246
9 1 9 51 641 235
10 1 10 905 743 313
是当天第一班延误航班之前的飞行次数(如上面链接中的问题所希望的那样)。
答案 0 :(得分:0)
您可以在逻辑向量上使用which.max
来确定满足条件的第一个实例。您还需要检查实际发生的情况。
library(dplyr)
library(nycflights13)
flights %>%
mutate(dep_delay = coalesce(dep_delay, 0)) %>%
arrange(month, day, dep_time) %>%
group_by(tailnum) %>%
summarise(max_delay = max(dep_delay),
which_first_geq_1hr = which.max(dep_delay > 60)) %>%
ungroup %>%
filter(max_delay > 60)
我假设延迟意味着出发延迟,NA
延迟意味着0
或至少少于一个小时,而我忽略了“未能”延迟超过一个小时的飞机。 coalesce
是避免which.max(NA)
所必需的。
答案 1 :(得分:0)
问题是每架飞机,所以您真的想按tailnum
分组进行操作。您可以添加一个标志列,但实际上您最终需要传递给filter
(逻辑向量)或slice
(行索引的向量)。有多种方法可以做到这一点,例如slice(seq(c(which(dep_delay > 60) - 1, n())[1]))
,但是一种不错的方法是使用dplyr的cumall
(all
的累积版本,例如cumsum
到sum
)来生成逻辑向量filter
:
library(dplyr)
nycflights13::flights %>%
group_by(tailnum) %>%
arrange(year, month, day, dep_time) %>% # ensure order before cumany
filter(cumall(pmax(dep_delay, arr_delay) < 60)) %>%
tally() # count number of observations per group (tailnum)
#> # A tibble: 3,709 x 2
#> # Groups: tailnum [3,709]
#> tailnum n
#> <chr> <int>
#> 1 N10156 9
#> 2 N102UW 25
#> 3 N103US 46
#> 4 N104UW 3
#> 5 N105UW 22
#> 6 N107US 20
#> 7 N108UW 36
#> 8 N109UW 28
#> 9 N110UW 15
#> 10 N11107 7
#> # ... with 3,699 more rows
可以创建一个中间表,其中包含前几个大延迟,并在它们所在的位置进行ID的自联接,或者使用if_else
向某些观测值添加标志值,但是无论如何,将子集设置为这些行将仍然需要与以上cumall
类似的逻辑,因此它们实际上只是更长,更慢的方法。