library(conflicted)
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.5.1     ✔ tibble    3.2.1
## ✔ lubridate 1.9.3     ✔ tidyr     1.3.1
## ✔ purrr     1.0.2
library(arrow)
library(slider) #ウィンドウ処理に便利なパッケージ

# ファイルの読み込み
hotel <- read_parquet("https://github.com/ghmagazine/awesomebook_v2/raw/main/data/hotel.parquet")
reservation <- read_parquet("https://github.com/ghmagazine/awesomebook_v2/raw/main/data/reservation.parquet")

14-1 順序のないウィンドウ関数

Q: ホテルマスタに対してホテルのある市区町村の平均価格の付与

Not Awesome

# (2) hotelに(1)の結果を左結合
hotel |>
  # (1)address_prefectureとaddress_cityごとにunit_priceの平均を算出
  left_join(
    hotel |>
      group_by(address_prefecture, address_city) |>
      summarise(avg_price_within_city = mean(unit_price, na.rm = TRUE)),
    by = c("address_prefecture", "address_city")
    )
## `summarise()` has grouped output by 'address_prefecture'. You can override
## using the `.groups` argument.
## # A tibble: 5,000 × 40
##    hotel_id hotel_name   hotel_type address_prefecture address_city address_town
##       <int> <chr>        <chr>      <chr>              <chr>        <chr>       
##  1        1 北飯岡ホテル ビジネス…  岩手県             盛岡市       北飯岡      
##  2        2 西二条南温…  リゾート…  北海道             中川郡美深町 西二条南    
##  3        3 小屋敷ペン…  民宿       青森県             黒石市       小屋敷      
##  4        4 中後町民宿   民宿       愛知県             碧南市       中後町      
##  5        5 鵜沼台ホテル ビジネス…  岐阜県             各務原市     鵜沼台      
##  6        6 新町ホテル   ビジネス…  熊本県             宇土市       新町        
##  7        7 七ツ山リゾ…  リゾート…  宮崎県             東臼杵郡諸…  七ツ山      
##  8        8 大山町ペン…  民宿       神奈川県           相模原市緑区 大山町      
##  9        9 新道ホテル   ビジネス…  北海道             上磯郡木古…  新道        
## 10       10 下奈良上ノ…  旅館       京都府             八幡市       下奈良上ノ段
## # ℹ 4,990 more rows
## # ℹ 34 more variables: address_zipcode <chr>, unit_price <int>,
## #   user_rating <dbl>, tag_001 <int>, tag_002 <int>, tag_003 <int>,
## #   tag_004 <int>, tag_005 <int>, tag_006 <int>, tag_007 <int>, tag_008 <int>,
## #   tag_009 <int>, tag_010 <int>, tag_011 <int>, tag_012 <int>, tag_013 <int>,
## #   tag_014 <int>, tag_015 <int>, tag_016 <int>, tag_017 <int>, tag_018 <int>,
## #   tag_019 <int>, tag_020 <int>, tag_021 <int>, tag_022 <int>, …

Awesome

hotel |>
  group_by(address_prefecture, address_city) |>
  mutate(avg_price_within_city = mean(unit_price, na.rm = TRUE)) |>
  ungroup()
## # A tibble: 5,000 × 40
##    hotel_id hotel_name   hotel_type address_prefecture address_city address_town
##       <int> <chr>        <chr>      <chr>              <chr>        <chr>       
##  1        1 北飯岡ホテル ビジネス…  岩手県             盛岡市       北飯岡      
##  2        2 西二条南温…  リゾート…  北海道             中川郡美深町 西二条南    
##  3        3 小屋敷ペン…  民宿       青森県             黒石市       小屋敷      
##  4        4 中後町民宿   民宿       愛知県             碧南市       中後町      
##  5        5 鵜沼台ホテル ビジネス…  岐阜県             各務原市     鵜沼台      
##  6        6 新町ホテル   ビジネス…  熊本県             宇土市       新町        
##  7        7 七ツ山リゾ…  リゾート…  宮崎県             東臼杵郡諸…  七ツ山      
##  8        8 大山町ペン…  民宿       神奈川県           相模原市緑区 大山町      
##  9        9 新道ホテル   ビジネス…  北海道             上磯郡木古…  新道        
## 10       10 下奈良上ノ…  旅館       京都府             八幡市       下奈良上ノ段
## # ℹ 4,990 more rows
## # ℹ 34 more variables: address_zipcode <chr>, unit_price <int>,
## #   user_rating <dbl>, tag_001 <int>, tag_002 <int>, tag_003 <int>,
## #   tag_004 <int>, tag_005 <int>, tag_006 <int>, tag_007 <int>, tag_008 <int>,
## #   tag_009 <int>, tag_010 <int>, tag_011 <int>, tag_012 <int>, tag_013 <int>,
## #   tag_014 <int>, tag_015 <int>, tag_016 <int>, tag_017 <int>, tag_018 <int>,
## #   tag_019 <int>, tag_020 <int>, tag_021 <int>, tag_022 <int>, …

Q: 都道府県ごとのホテル数の構成比の算出

Awesome

hotel |>
  summarise(hotel_cnt = n(), .by = address_prefecture) |>
  mutate(ratio = hotel_cnt / sum(hotel_cnt))
## # A tibble: 47 × 3
##    address_prefecture hotel_cnt  ratio
##    <chr>                  <int>  <dbl>
##  1 岩手県                    70 0.014 
##  2 北海道                   365 0.073 
##  3 青森県                    83 0.0166
##  4 愛知県                   318 0.0636
##  5 岐阜県                   130 0.026 
##  6 熊本県                    64 0.0128
##  7 宮崎県                    41 0.0082
##  8 神奈川県                 114 0.0228
##  9 京都府                   261 0.0522
## 10 福井県                    69 0.0138
## # ℹ 37 more rows

14-2 順序のあるウィンドウ関数

Q: 各顧客の一つ前と二つ前の予約の予約金額の取得

Awesome

test <- reservation |>
  # (1)reserved_atの昇順(時系列順)にソート
  group_by(customer_id) |>  
  arrange(reserved_at, .by_group = TRUE) |>
  # (2)customer_idごとに一つ前と二つ前の行のtotal_priceを取得
  mutate(
    total_price_at_prev = dplyr::lag(total_price, n = 1),
    total_price_at_2prev = dplyr::lag(total_price, n = 2)
  ) |>
  ungroup()

Q: 顧客ごとに予約順を付与

Awesome

reservation |>
  group_by(customer_id) |>
  mutate(reservation_no = dense_rank(reserved_at)) |>
  ungroup()
## # A tibble: 2,000,000 × 12
##    reservation_id hotel_id customer_id reserved_at         checkin_date       
##             <int>    <int>       <int> <dttm>              <dttm>             
##  1              1     2460       53431 2013-12-31 07:00:14 2014-12-31 00:00:00
##  2              2      962      488390 2013-12-31 08:23:35 2014-12-31 00:00:00
##  3              3      558      341335 2013-12-31 09:02:05 2014-12-31 00:00:00
##  4              4     3666      398981 2013-12-31 23:44:54 2014-12-31 00:00:00
##  5              5     2180      220381 2014-01-01 02:47:50 2014-12-31 00:00:00
##  6              6      974        1494 2014-01-01 07:56:58 2015-01-01 00:00:00
##  7              7     2260       24104 2014-01-01 13:17:06 2014-12-30 00:00:00
##  8              8      314      124883 2014-01-01 14:22:01 2014-12-31 00:00:00
##  9              9     2211       45282 2014-01-01 14:59:04 2014-12-31 00:00:00
## 10             10      333      390595 2014-01-01 20:24:34 2014-12-30 00:00:00
## # ℹ 1,999,990 more rows
## # ℹ 7 more variables: checkout_date <dttm>, length_of_stay <int>,
## #   people_num <int>, total_price <int>, status <chr>, canceled_at <dttm>,
## #   reservation_no <int>

14-3 範囲のあるウィンドウ関数

Q: 売上の移動平均の算出

Awesome

移動平均を算出するにはいくつかの方法がある。ここでは以下の三つのやり方を紹介する。

  • zooパッケージのrollmean()関数。古典的な方法。
  • RcppRollパッケージのroll_mean()関数。C++実装で処理が高速。
  • sliderパッケージのslide_vec()関数。tidyverseフレンドリーで複雑な処理に対応可能。
zooパッケージのrollmean()関数
# 必要なパッケージを読み込み
library(zoo) #rollmean

reservation |>
  # (1) キャンセルを除去
  dplyr::filter(status != "canceled") |>
  # (2) checkout_dateを月周期のPeriodに変換
  mutate(month = floor_date(as_date(checkout_date), "month")) |>
  # (3) monthごとにtotal_priceの総和を計算(集計結果はmonth順に並ぶ)
  summarise(sales = sum(total_price, na.rm = TRUE), .by =month) |>
  arrange(month) |>
  # (4) salesの直近3行分の平均を計算
  mutate(moving_average_sales = rollmean(sales, 3, fill = NA, align = "right"))
## # A tibble: 60 × 3
##    month           sales moving_average_sales
##    <date>          <dbl>                <dbl>
##  1 2015-01-01  730844200                  NA 
##  2 2015-02-01  650411000                  NA 
##  3 2015-03-01 1447995200           943083467.
##  4 2015-04-01  697578500           931994900 
##  5 2015-05-01 2185718000          1443763900 
##  6 2015-06-01  697210900          1193502467.
##  7 2015-07-01 1465165300          1449364733.
##  8 2015-08-01 2910478200          1690951467.
##  9 2015-09-01  708236200          1694626567.
## 10 2015-10-01  733080000          1450598133.
## # ℹ 50 more rows
RcppRollパッケージのroll_mean()関数
# 必要なパッケージを読み込み
library(RcppRoll) #rollmean

reservation |>
  # (1) キャンセルを除去
  dplyr::filter(status != "canceled") |>
  # (2) checkout_dateを月周期のPeriodに変換
  mutate(month = floor_date(as_date(checkout_date), "month")) |>
  # (3) monthごとにtotal_priceの総和を計算(集計結果はmonth順に並ぶ)
  summarise(sales = sum(total_price, na.rm = TRUE), .by =month) |>
  arrange(month) |>
  # (4) salesの直近3行分の平均を計算
  mutate(moving_average_sales = roll_mean(sales, n = 3, fill = NA, align = "right"))
## # A tibble: 60 × 3
##    month           sales moving_average_sales
##    <date>          <dbl>                <dbl>
##  1 2015-01-01  730844200                  NA 
##  2 2015-02-01  650411000                  NA 
##  3 2015-03-01 1447995200           943083467.
##  4 2015-04-01  697578500           931994900 
##  5 2015-05-01 2185718000          1443763900 
##  6 2015-06-01  697210900          1193502467.
##  7 2015-07-01 1465165300          1449364733.
##  8 2015-08-01 2910478200          1690951467.
##  9 2015-09-01  708236200          1694626567.
## 10 2015-10-01  733080000          1450598133.
## # ℹ 50 more rows
sliderパッケージのslide_vec()関数
# 必要なパッケージを読み込み
library(slider)

tictoc::tic()
reservation |>
  # (1) キャンセルを除去
  dplyr::filter(status != "canceled") |>
  # (2) checkout_dateを月周期のPeriodに変換
  mutate(month = floor_date(as_date(checkout_date), "month")) |>
  # (3) monthごとにtotal_priceの総和を計算(集計結果はmonth順に並ぶ)
  summarise(sales = sum(total_price, na.rm = TRUE), .by =month) |>
  arrange(month) |>
  # (4) salesの直近3行分の平均を計算
  mutate(moving_average_sales = slide_vec(.x = sales, .f = mean, .before = 2, .complete = TRUE))
## # A tibble: 60 × 3
##    month           sales moving_average_sales
##    <date>          <dbl>                <dbl>
##  1 2015-01-01  730844200                  NA 
##  2 2015-02-01  650411000                  NA 
##  3 2015-03-01 1447995200           943083467.
##  4 2015-04-01  697578500           931994900 
##  5 2015-05-01 2185718000          1443763900 
##  6 2015-06-01  697210900          1193502467.
##  7 2015-07-01 1465165300          1449364733.
##  8 2015-08-01 2910478200          1690951467.
##  9 2015-09-01  708236200          1694626567.
## 10 2015-10-01  733080000          1450598133.
## # ℹ 50 more rows
tictoc::toc()
## 7.25 sec elapsed

Q: 顧客の過去の総予約金額を付与

Awesome

reservation |>
  #(1)キャンセル済みのデータを除去
  dplyr::filter(status != "canceled") |>
  #(2)reserved_atの昇順(時系列順)にソート
  arrange(reserved_at) |>
  mutate(
    #(3)customer_idごとにtotal_priceを時系列順に1行分ずらす
    #(4)customer_idごとにprev_total_priceの累計和を計算
    past_total_spent = total_price |>
      dplyr::lag(n = 1) |>
      coalesce(0) |>
      cumsum(),
    .by = customer_id
  )
## # A tibble: 1,799,589 × 12
##    reservation_id hotel_id customer_id reserved_at         checkin_date       
##             <int>    <int>       <int> <dttm>              <dttm>             
##  1              1     2460       53431 2013-12-31 07:00:14 2014-12-31 00:00:00
##  2              2      962      488390 2013-12-31 08:23:35 2014-12-31 00:00:00
##  3              3      558      341335 2013-12-31 09:02:05 2014-12-31 00:00:00
##  4              4     3666      398981 2013-12-31 23:44:54 2014-12-31 00:00:00
##  5              5     2180      220381 2014-01-01 02:47:50 2014-12-31 00:00:00
##  6              6      974        1494 2014-01-01 07:56:58 2015-01-01 00:00:00
##  7              7     2260       24104 2014-01-01 13:17:06 2014-12-30 00:00:00
##  8              8      314      124883 2014-01-01 14:22:01 2014-12-31 00:00:00
##  9              9     2211       45282 2014-01-01 14:59:04 2014-12-31 00:00:00
## 10             10      333      390595 2014-01-01 20:24:34 2014-12-30 00:00:00
## # ℹ 1,799,579 more rows
## # ℹ 7 more variables: checkout_date <dttm>, length_of_stay <int>,
## #   people_num <int>, total_price <int>, status <chr>, canceled_at <dttm>,
## #   past_total_spent <dbl>

Awesome

総和を求めてから対象行の金額を引く方法。こっちの方が圧倒的に速い。

reservation |>
  # (1) キャンセル済みのデータを除去
  dplyr::filter(status != "canceled") |>
  # (2) reserved_atの昇順(時系列順)にソート
  arrange(reserved_at) |>
  # (3) customer_idごとにtotal_priceの累計和を計算し、現在の行の値を減算
  mutate(
    past_total_spent = cumsum(total_price) - total_price,
    .by = customer_id
    )
## # A tibble: 1,799,589 × 12
##    reservation_id hotel_id customer_id reserved_at         checkin_date       
##             <int>    <int>       <int> <dttm>              <dttm>             
##  1              1     2460       53431 2013-12-31 07:00:14 2014-12-31 00:00:00
##  2              2      962      488390 2013-12-31 08:23:35 2014-12-31 00:00:00
##  3              3      558      341335 2013-12-31 09:02:05 2014-12-31 00:00:00
##  4              4     3666      398981 2013-12-31 23:44:54 2014-12-31 00:00:00
##  5              5     2180      220381 2014-01-01 02:47:50 2014-12-31 00:00:00
##  6              6      974        1494 2014-01-01 07:56:58 2015-01-01 00:00:00
##  7              7     2260       24104 2014-01-01 13:17:06 2014-12-30 00:00:00
##  8              8      314      124883 2014-01-01 14:22:01 2014-12-31 00:00:00
##  9              9     2211       45282 2014-01-01 14:59:04 2014-12-31 00:00:00
## 10             10      333      390595 2014-01-01 20:24:34 2014-12-30 00:00:00
## # ℹ 1,799,579 more rows
## # ℹ 7 more variables: checkout_date <dttm>, length_of_stay <int>,
## #   people_num <int>, total_price <int>, status <chr>, canceled_at <dttm>,
## #   past_total_spent <int>

Q: 顧客の過去の総予約金額を付与

これはsliderパッケージのslider::slide_*()関数が便利。

Awesome

reservation |>
  dplyr::filter(customer_id < 10) |>
  mutate(reserved_at_date = as_date(reserved_at)) |>
  # (1) キャンセル済みのデータを除去
  dplyr::filter(status != "canceled") %>%
  # (2) reserved_atの昇順(時系列順)にソート
  arrange(reserved_at) %>%
  # (3)
  mutate(
    total_spent_last_90days = slide_period_dbl(
      .x = total_price,             # 累積合計を計算する変数
      .i = reserved_at_date,        # インデックス変数
      .period = "day",              # 期間の単位 ("day", "month", "year"など)
      .before = 90L,                # 過去90日間の期間
      .complete = FALSE,            # 完全な期間でない場合でも計算を行う
      ~ sum(.x, na.rm = TRUE)       # 関数: ここで累積合計が計算される
    ) - total_price,
    .by = customer_id
  )
## # A tibble: 47 × 13
##    reservation_id hotel_id customer_id reserved_at         checkin_date       
##             <int>    <int>       <int> <dttm>              <dttm>             
##  1          12086     1282           1 2014-04-16 13:39:41 2015-03-03 00:00:00
##  2          19584     2498           2 2014-05-12 23:16:19 2015-03-15 00:00:00
##  3         128306     2889           4 2014-10-26 00:02:54 2015-08-01 00:00:00
##  4         159766     1454           7 2014-11-28 01:33:41 2015-11-14 00:00:00
##  5         178009      848           9 2014-12-15 21:34:58 2015-07-01 00:00:00
##  6         192936       58           6 2014-12-29 18:40:24 2015-07-09 00:00:00
##  7         225337     2977           6 2015-01-28 03:02:40 2015-09-23 00:00:00
##  8         244272      177           7 2015-02-14 08:00:28 2015-08-16 00:00:00
##  9         335066     2462           7 2015-05-07 14:26:31 2015-12-28 00:00:00
## 10         348951     1219           2 2015-05-20 13:27:27 2015-08-03 00:00:00
## # ℹ 37 more rows
## # ℹ 8 more variables: checkout_date <dttm>, length_of_stay <int>,
## #   people_num <int>, total_price <int>, status <chr>, canceled_at <dttm>,
## #   reserved_at_date <date>, total_spent_last_90days <dbl>

14-4 指定列が最小/最大となる行の取得

Q:顧客の初回予約時の情報の取得

Not Awesome

普通に考えるとslice_min()を使いたくなるが、これは実装の問題で処理が遅い。

reservation |>
  select(customer_id, reserved_at, hotel_id) |>
  group_by(customer_id) |>
  slice_min(reserved_at, n = 1)
## # A tibble: 417,368 × 3
## # Groups:   customer_id [417,368]
##    customer_id reserved_at         hotel_id
##          <int> <dttm>                 <int>
##  1           1 2014-04-16 13:39:41     1282
##  2           2 2014-05-12 23:16:19     2498
##  3           3 2016-02-13 14:07:40     1649
##  4           4 2014-10-26 00:02:54     2889
##  5           5 2016-05-06 11:31:47     3306
##  6           6 2014-12-29 18:40:24       58
##  7           7 2014-11-28 01:33:41     1454
##  8           8 2015-10-10 14:45:54     4341
##  9           9 2014-12-15 21:34:58      848
## 10          10 2018-08-31 06:45:30     3111
## # ℹ 417,358 more rows

Awesome

予約順の番号を付与して、1番を抽出する方が処理が速い。

reservation |>
  # (1) 顧客ごとに予約順の番号を付与
  group_by(customer_id) |>
  mutate(rn = dense_rank(reserved_at)) |>
  # (2) 顧客の最初の予約のみ抽出
  dplyr::filter(rn == 1) |>
  select(customer_id, reserved_at, hotel_id)
## # A tibble: 417,368 × 3
## # Groups:   customer_id [417,368]
##    customer_id reserved_at         hotel_id
##          <int> <dttm>                 <int>
##  1       53431 2013-12-31 07:00:14     2460
##  2      488390 2013-12-31 08:23:35      962
##  3      341335 2013-12-31 09:02:05      558
##  4      398981 2013-12-31 23:44:54     3666
##  5      220381 2014-01-01 02:47:50     2180
##  6        1494 2014-01-01 07:56:58      974
##  7       24104 2014-01-01 13:17:06     2260
##  8      124883 2014-01-01 14:22:01      314
##  9       45282 2014-01-01 14:59:04     2211
## 10      390595 2014-01-01 20:24:34      333
## # ℹ 417,358 more rows

14-5 層別サンプリング

Q: 都道府県別に層別サンプリング

Not Awesome

10%のデータをランダムサンプリング

hotel |>
  slice_sample(prop = 0.1)
## # A tibble: 500 × 39
##    hotel_id hotel_name   hotel_type address_prefecture address_city address_town
##       <int> <chr>        <chr>      <chr>              <chr>        <chr>       
##  1     4571 光珠内東山…  旅館       北海道             美唄市       光珠内東山  
##  2     1614 三ツ橋ペン…  民宿       新潟県             上越市       三ツ橋      
##  3     1538 豊玉町志多…  旅館       長崎県             対馬市       豊玉町志多浦
##  4     3104 こも原町ビ…  ビジネス…  愛知県             名古屋市西区 こも原町    
##  5     3303 北方町板上…  リゾート…  宮崎県             延岡市       北方町板上  
##  6     3658 水橋市江旅館 旅館       富山県             富山市       水橋市江    
##  7     1541 上の原ホテル リゾート…  東京都             東久留米市   上の原      
##  8     2726 大篠ペンシ…  民宿       岡山県             津山市       大篠        
##  9     3560 小平旅館     旅館       宮城県             亘理郡山元町 小平        
## 10     2704 中津原ホテル ビジネス…  新潟県             村上市       中津原      
## # ℹ 490 more rows
## # ℹ 33 more variables: address_zipcode <chr>, unit_price <int>,
## #   user_rating <dbl>, tag_001 <int>, tag_002 <int>, tag_003 <int>,
## #   tag_004 <int>, tag_005 <int>, tag_006 <int>, tag_007 <int>, tag_008 <int>,
## #   tag_009 <int>, tag_010 <int>, tag_011 <int>, tag_012 <int>, tag_013 <int>,
## #   tag_014 <int>, tag_015 <int>, tag_016 <int>, tag_017 <int>, tag_018 <int>,
## #   tag_019 <int>, tag_020 <int>, tag_021 <int>, tag_022 <int>, …

Awesome

address_prefecture列の値ごとに10%のデータをランダムサンプリング

hotel |>
  group_by(address_prefecture) |>
  slice_sample(prop = 0.1)
## # A tibble: 483 × 39
## # Groups:   address_prefecture [47]
##    hotel_id hotel_name  hotel_type  address_prefecture address_city address_town
##       <int> <chr>       <chr>       <chr>              <chr>        <chr>       
##  1     2376 坂本旅館    旅館        三重県             多気郡明和町 坂本        
##  2     4051 藤原町石川… 民宿        三重県             いなべ市     藤原町石川  
##  3     4293 薦生温泉ホ… リゾートホ… 三重県             名張市       薦生        
##  4      930 星見ケ丘温… 旅館        三重県             桑名市       星見ケ丘    
##  5     1820 掛樋温泉ホ… リゾートホ… 三重県             桑名市       掛樋        
##  6      197 長深ホテル  ビジネスホ… 三重県             員弁郡東員町 長深        
##  7     2435 神島町ビジ… ビジネスホ… 三重県             鳥羽市       神島町      
##  8     3569 佐田ビジネ… ビジネスホ… 三重県             度会郡玉城町 佐田        
##  9      212 田中大堰町… 旅館        京都府             京都市左京区 田中大堰町  
## 10       94 北町温泉ホ… リゾートホ… 京都府             京都市下京区 北町        
## # ℹ 473 more rows
## # ℹ 33 more variables: address_zipcode <chr>, unit_price <int>,
## #   user_rating <dbl>, tag_001 <int>, tag_002 <int>, tag_003 <int>,
## #   tag_004 <int>, tag_005 <int>, tag_006 <int>, tag_007 <int>, tag_008 <int>,
## #   tag_009 <int>, tag_010 <int>, tag_011 <int>, tag_012 <int>, tag_013 <int>,
## #   tag_014 <int>, tag_015 <int>, tag_016 <int>, tag_017 <int>, tag_018 <int>,
## #   tag_019 <int>, tag_020 <int>, tag_021 <int>, tag_022 <int>, …

14-6 グループ単位のランダムサンプリング

Q: 顧客単位で予約履歴をランダムサンプリング

Not Awesome

20000件をランダムサンプリング

reservation |>
  slice_sample(n = 20000)
## # A tibble: 20,000 × 11
##    reservation_id hotel_id customer_id reserved_at         checkin_date       
##             <int>    <int>       <int> <dttm>              <dttm>             
##  1        1471710     2763      390797 2018-03-11 16:01:44 2018-10-06 00:00:00
##  2         886330     3850      427801 2016-09-23 10:43:16 2017-06-27 00:00:00
##  3         451908     2521      185794 2015-08-22 23:57:39 2015-12-26 00:00:00
##  4        1474357     1522      497835 2018-03-14 02:08:36 2018-12-01 00:00:00
##  5        1660033      777      420582 2018-08-30 02:56:50 2019-08-27 00:00:00
##  6          30143     2362      405702 2014-06-07 13:18:50 2015-03-26 00:00:00
##  7        1840659      650      219057 2019-02-12 02:11:04 2019-08-04 00:00:00
##  8         892152     1196      363390 2016-09-28 19:17:02 2017-03-05 00:00:00
##  9         289641     3041      454994 2015-03-27 04:10:09 2015-10-31 00:00:00
## 10        1186405     2805      301936 2017-06-24 03:22:36 2017-12-28 00:00:00
## # ℹ 19,990 more rows
## # ℹ 6 more variables: checkout_date <dttm>, length_of_stay <int>,
## #   people_num <int>, total_price <int>, status <chr>, canceled_at <dttm>

Awesome

# (1)顧客をサンプリング
sampled_customers <- reservation |>
  distinct(customer_id) |>
  slice_sample(prop = 0.01)

# (2) サンプリングした顧客の予約を抽出する
reservation |>
  dplyr::filter(customer_id %in% sampled_customers$customer_id)|>
  summarise(n = n(), .by = customer_id) |>
  summarise(mean = mean(n))
## # A tibble: 1 × 1
##    mean
##   <dbl>
## 1  4.86

以上です。

第15章 演習問題

第13章 文字列

Top