R for Data Scienceの例題を解く- Chapter 16 日付と時刻

神Hadley R for Data Science の例題たちとその解答を書き残します。
今回はChapter 16 Dates and timesです。

過去の記事

この章では基本のtidyverseに加えてlubridateライブラリを使います。
あと分析デモ用データとしてnycflights13を使います。

library(tidyverse)

library(lubridate)
library(nycflights13)

Chapter 16 Dates and times

16.2 Creating date/times

16.2.4 Exercises

1. What happens if you parse a string that contains invalid dates?

ymd(c("2010-10-10", "bananas"))
#[1] "2010-10-10" NA
#Warning message:
# 1 failed to parse.

Warningが出てNAを返す。

2. What does the tzone argument today() do? Why is it important?

tzoneオプションを使えば異なるタイムゾーンの今日を得ることができる。

3. Use the appropriate lubridate function to parse each of the following dates:

d1 <- "January 1, 2010"
d2 <- "2015-Mar-07"
d3 <- "06-Jun-2017"
d4 <- c("August 19 (2015)", "July 1 (2015)")
d5 <- "12/30/14" # Dec 30, 2014
mdy(d1)
#[1] "2010-01-01"
ymd(d2)
#[1] "2015-03-07"
dmy(d3)
#[1] "2017-06-06"
mdy(d4)
#[1] "2015-08-19" "2015-07-01"
mdy(d5)
#[1] "2014-12-30"

柔軟すぎてしゅごい

16.3 Date-time components

16.3.4 Exercises

1. How does the distribution of flight times within a day change over the course of the year?

flights_dt <- flights %>% 
  filter(!is.na(dep_time), !is.na(arr_time)) %>% 
  mutate(
    dep_time = make_datetime_100(year, month, day, dep_time),
    arr_time = make_datetime_100(year, month, day, arr_time),
    sched_dep_time = make_datetime_100(year, month, day, sched_dep_time),
    sched_arr_time = make_datetime_100(year, month, day, sched_arr_time)
  ) %>% 
  select(origin, dest, ends_with("delay"), ends_with("time"))
flights_dt %>%
  mutate(
    hour = dep_time %>% hour %>% factor,
    month = month(dep_time, label = TRUE)
  ) %>%
  count(month, hour) %>%
  ggplot(aes(month, n)) +
    geom_line(aes(color = hour, group = hour)) +
    geom_text(aes(label = hour))
出発時間の分布の季節推移

2. Compare dep_time, sched_dep_time and dep_delay. Are they consistent? Explain your findings.

flights %>% select(dep_time, sched_dep_time, dep_delay) %>% filter(dep_delay > 100)
## A tibble: 13,346 x 3
#   dep_time sched_dep_time dep_delay
#      <int>          <int>     <dbl>
# 1      811            630       101
# 2      848           1835       853
# 3      957            733       144
# 4     1114            900       134
# 5     1505           1310       115
# 6     1525           1340       105
# 7     1540           1338       122
# 8     1558           1359       119
# 9     1803           1620       103
#10     1815           1325       290

dep_time, sched_dep_timeは時刻で、下二桁が分を上二桁が時間を表している。
一方dep_delayは遅延時間を表しており単位は分、三桁目は100分の単位で素直に10進数で繰り上がるようになっている。
素朴にはdep_timesched_dep_timeの差はdep_delayになるはずだが、表現方法が異なるため単純な計算では一致しない。

3. Compare air_time with the duration between the departure and arrival. Explain your findings.

air_timedep_delayと同じく単位は分。
さらに時差がありarr_timeは現地時刻を表しているため、arr_timedep_timeの差がair_timeにすらならない。

4. How does the average delay time change over the course of a day? Should you use dep_time or sched_dep_time? Why?

d1 <- flights %>% group_by(dep_hour = dep_time %/% 100) %>% summarise(dep_delay = mean(dep_delay, na.rm=TRUE), n = n())
d2 <- flights %>% group_by(dep_hour = sched_dep_time %/% 100) %>% summarise(dep_delay = mean(dep_delay, na.rm=TRUE), n = n())
bind_rows(d1 %>% mutate(cat = "act"), d2 %>% mutate(cat = "sched")) %>% ggplot(aes(dep_hour, dep_delay)) + geom_point(aes(color = cat, size = n), alpha = 0.8)

出発時刻ごとの遅延時間

dep_timeでみたとき、早朝は平均遅延時間が大きく出ているが、これは早朝にいつも遅れているというわけではない。
元々早朝に出発するフライト予定が無いため、遅延したフライトのみが早朝に出発しているため常に遅れているように見える。
この種の偏りを排除するためにはsched_dep_timeを見るべきという気がする。
そもそも実際に出発する時間は我々はコントロールできず、できるのは予約時点で予定出発時刻を選択することだけであるから、shced_dep_timeにしか見る意味はない。

5. On what day of the week should you leave if you want to minimise the chance of a delay?

flights_dt %>%
  mutate(wday = wday(sched_dep_time, label = TRUE)) %>%
  ggplot(aes(wday, arr_delay)) +
    geom_boxplot(aes(group = wday)) +
    scale_y_log10()

曜日ごとの遅延時間の箱ひげ図。縦軸は対数軸

少しわかりにくいが土曜日だけがすべての指標で小さい。
すなわち出発すべきは土曜日。

6. What makes the distribution of diamonds$carat and flights$sched_dep_time similar?

flights_dt %>%
  mutate(sched_dep_time = update(sched_dep_time, yday = 1)) %>%
  ggplot(aes(sched_dep_time)) +
    geom_histogram(bins = 100)

出発時刻のヒストグラム

どちらもキリの良い時間に分布が集中している。

7. Confirm my hypothesis that the early departures of flights in minutes 20-30 and 50-60 are caused by scheduled flights that leave early.

flights_dt %>%
  mutate(
    min_cut = cut_width(minute(dep_time), 10, boundary = 0),
    hour = hour(dep_time),
    delayed = dep_delay > 0
  ) %>%
  filter(hour %in% 5:20) %>%
  group_by(min_cut, hour) %>%
  summarise(delay_ratio = mean(delayed, na.rm=TRUE)) %>%
  ggplot(aes(hour, delay_ratio)) +
    geom_line(aes(group = min_cut, color = min_cut))


全時間帯とおして50分台は遅れる率が低い(=早く出発する率が高い)。
午前中では20分台、50分台で80%以上の割合で早く出発している。

16.4 Time spans

16.4.5 Exercises

1. Why is there months() but no dmonths()?

一ヶ月は30日と31日とが半々のため、何秒かという共通指標が存在しないから。

2. Explain days(overnight * 1) to someone who has just started learning R. How does it work?

overnightは論理値ベクトルでフライトが日をまたいでいるときTRUEになる。
overnight * 1という計算をするとovernightTRUEのとき1で、FALSEのとき0となる数値ベクトルになる。
よってdays(overnight * 1)overnightするときは1日、そうでないときは0日のintervalベクトルになる。

3. Create a vector of dates giving the first day of every month in 2015. Create a vector of dates giving the first day of every month in the current year.

ymd(20150101) + months(0:11)
# [1] "2015-01-01" "2015-02-01" "2015-03-01" "2015-04-01" "2015-05-01" "2015-06-01" "2015-07-01" "2015-08-01" "2015-09-01" "2015-10-01" "2015-11-01" "2015-12-01"
make_date(year(today()), 1,1) + months(0:11)
# "2019-01-01" "2019-02-01" "2019-03-01" "2019-04-01" "2019-05-01" "2019-06-01" "2019-07-01" "2019-08-01" "2019-09-01" "2019-10-01" "2019-11-01" "2019-12-01"

4. Write a function that given your birthday (as a date), returns how old you are in years.

how_old <- function(date){
 (date %--% today()) %/% years(1)
}
how_old(ymd(19850507))
#Note: method with signature ‘Timespan#Timespan’ chosen for function ‘%/%’,
# target signature ‘Interval#Period’.
# "Interval#ANY", "ANY#Period" would also be valid
# [1] 33

5. Why can’t (today() %--% (today() + years(1)) / months(1) work?

(today() %--% (today() + years(1))) / months(1)
# [1] 12

まず問題文の分子で閉じカッコが一つ足りない。
それを足すと普通に処理できてしまった。
何がおかしいのか分からない。

コメントを残す