我有一些包含酒店客房预订信息的数据,看起来像下面的示例:
user_id h_name h_capacity check_in_date check_out_date
1 A1 2 2019-01-01 2019-01-05
2 A1 2 2019-01-02 2019-01-05
3 A1 2 2019-01-02 2019-01-03
4 A2 3 2019-01-02 2019-01-04
5 A2 3 2019-01-04 2019-01-05
user_id
:客户ID
h_name
:酒店名称
h_capacity
:酒店的最大房间数。
check_in_date
和check_out_date
:不言自明。
我的目的是找出哪些酒店正在按规定的容量接待人员。
我尝试的方法涉及到为每个日期创建新列,从而导致上面给出示例数据框。看起来如下:
<...> 2019-01-01 2019-01-02 2019-01-03 2019-01-04 2019-01-05
<...> 0 0 0 0 0
<...> 0 0 0 0 0
<...> 0 0 0 0 0
<...> 0 0 0 0 0
<...> 0 0 0 0 0
<...>
表示出现在顶部第一个数据框中的列。
完成上述操作后,我想将数字1插入用户在酒店居住的日期的列中,结果如下所示:
<...> 2019-01-01 2019-01-02 2019-01-03 2019-01-04 2019-01-05
<...> 1 1 1 1 1
<...> 0 1 1 1 1
<...> 0 1 1 0 0
<...> 0 1 1 1 0
<...> 0 0 0 1 1
<...>
代表显示在顶部示例中的列。
最后,我只需要在h_name上使用summary来获取每天的床位总数。
问题是我无法在该人已占用房间的日期列中用值1
填充上面显示的数据框。 这涉及将值填充到每一行的不同列中,这意味着对于用户而言,我需要将1
插入代表他们在酒店停留日期的列中。并没有找到最佳解决方案,最终使用了for
循环来执行,该循环耗时32分钟。
我为此谦虚地寻求最佳解决方案。 (请注意:数据有50万行)
答案 0 :(得分:3)
我没有遵循您的方法,但这可以解决您的问题。注意:我假设酒店的容量会随着时间的推移而保持不变,并且退房日期将像您在示例中一样计为床位。
library(tidyverse)
hotel_data %>%
gather(check_in, date, check_in_date, check_out_date) %>%
group_by(h_name, h_capacity, user_id) %>%
complete(date = seq.Date(first(date), last(date), by = "day"),
fill = list(check_in = "stay")) %>%
group_by(h_name, date) %>%
mutate(people = n()) %>%
filter(people > h_capacity)
# A tibble: 6 x 6
# Groups: h_name, date [2]
# h_name h_capacity user_id date check_in people
# <chr> <dbl> <dbl> <date> <chr> <int>
# 1 A1 2 1 2019-01-02 stay 3
# 2 A1 2 1 2019-01-03 stay 3
# 3 A1 2 2 2019-01-02 check_in_date 3
# 4 A1 2 2 2019-01-03 stay 3
# 5 A1 2 3 2019-01-02 check_in_date 3
# 6 A1 2 3 2019-01-03 check_out_date 3
说明
首先,我使用gather
将您的数据转换为长格式,因为使用complete
可以轻松地为每个组(酒店和用户)填写缺少的日期值。然后仅按酒店和日期分组,我计算人数,然后按超出人数的人数筛选。
数据
hotel_data <- structure(list(user_id = c(1, 2, 3, 4, 5),
h_name = c("A1", "A1", "A1", "A2", "A2"),
h_capacity = c(2, 2, 2, 3, 3),
check_in_date = structure(c(17897, 17898, 17898, 17898, 17900), class = "Date"),
check_out_date = structure(c(17901, 17901, 17899, 17900, 17901), class = "Date")),
class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -5L))