如何在R中计算跨月/跨年的酒店预订每月入住晚数?
跨月/跨年酒店预订的分月入住天数统计方案
核心逻辑
将每笔跨月/跨年的拆分为对应月份的独立记录,分别计算各月的入住天数后,按「年-月」维度汇总总数。以下以R语言为例给出两种实现方案(适配不同数据量场景):
方案1:生成每日记录拆分(适合中小数据集)
通过生成每笔预订的每日日期序列,再按年月分组统计天数,逻辑直观易理解:
library(dplyr) library(lubridate) # 确保日期列是Date类型 df$check_in <- as.Date(df$check_in) df$check_out <- as.Date(df$check_out) # 生成每笔预订的每日入住记录(退房当天不计入,若需计入则去掉`-1`) daily_records <- df %>% rowwise() %>% mutate(date = list(seq(check_in, check_out - 1, by = "day"))) %>% unnest(date) # 按年-月分组统计总入住天数 monthly_stats <- daily_records %>% mutate(year_month = floor_date(date, "month")) %>% group_by(year_month) %>% summarise(total_stay_days = n()) %>% arrange(year_month)
方案2:直接计算月度天数(适合大数据集)
无需生成每日记录,通过计算起始月剩余天数、中间整月天数、结束月天数来拆分,内存占用更低:
library(dplyr) library(lubridate) # 定义单条预订的分月天数计算函数 calc_monthly_days <- function(check_in, check_out) { in_ym <- floor_date(check_in, "month") out_ym <- floor_date(check_out, "month") if (in_ym == out_ym) { # 同月:直接计算天数(退房当天不计入) return(tibble(year_month = in_ym, days = as.integer(check_out - check_in))) } else { # 起始月天数:当月最后一天 - 入住日 last_day_in <- ceiling_date(check_in, "month") - 1 first_month_days <- as.integer(last_day_in - check_in) # 中间整月的天数 middle_months <- seq(in_ym %m+% months(1), out_ym %m-% months(1), by = "month") middle_days <- tibble(year_month = middle_months, days = days_in_month(middle_months)) # 结束月天数:退房日 - 当月第一天(退房当天不计入) first_day_out <- floor_date(check_out, "month") last_month_days <- as.integer(check_out - first_day_out) # 合并所有月份记录 bind_rows( tibble(year_month = in_ym, days = first_month_days), middle_days, tibble(year_month = out_ym, days = last_month_days) ) } } # 应用函数并汇总统计 monthly_stats <- df %>% rowwise() %>% mutate(monthly_data = list(calc_monthly_days(check_in, check_out))) %>% unnest(monthly_data) %>% group_by(year_month) %>% summarise(total_stay_days = sum(days)) %>% arrange(year_month)
关键注意事项
- 退房天数规则:代码默认退房当天不计入入住天数,若酒店规则为退房当天也算,需调整对应计算逻辑(如去掉
check_out - 1、修改结束月天数计算方式)。 - 日期格式校验:必须确保
check_in和check_out列是标准Date类型,避免字符串格式错误导致计算失败。
内容的提问来源于stack exchange,提问作者Sofia
相关产品推荐
相关产品推荐

