如何在R语言中统计日期区间内每日唯一ID的数量?
解决每日在住唯一ID统计问题
嘿,我来帮你搞定这个需求!你想要统计每一天有多少个唯一ID处于入住(in)和退房(out)日期之间对吧?咱们一步步来实现,先提个小提醒:in是R的保留关键字,直接用会报错,所以先把列名改成date_in和date_out会更稳妥。
核心思路
要么把每个ID的入住时间段拆成每一天的记录,再按天统计;要么生成所有需要的日期,逐一筛选符合条件的ID。下面给你两种实用的实现方式:
方法一:拆分时间段(直观易懂)
用lubridate处理日期,dplyr做数据清洗,tidyr拆分日期序列,适合数据量中等的情况:
# 加载所需包 library(lubridate) library(dplyr) library(tidyr) # 修正列名 + 转换日期格式(原始是dd-mm-yyyy,用dmy函数) df <- df %>% rename(date_in = `in`, date_out = out) %>% mutate( date_in = dmy(date_in), date_out = dmy(date_out) ) # 为每个ID生成入住期间的所有日期 df_expanded <- df %>% mutate(day = map2(date_in, date_out, seq, by = "day")) %>% unnest(day) # 按天统计唯一ID数量,再转回你需要的日期字符串格式 df2 <- df_expanded %>% group_by(day) %>% summarise(count = n_distinct(id)) %>% mutate(day = format(day, "%d-%m-%Y"))
方法二:直接筛选日期(高效省内存)
如果你的数据量很大,拆分日期会占用过多内存,这种方法更高效:
library(lubridate) library(dplyr) # 同样先修正列名和转换日期 df <- df %>% rename(date_in = `in`, date_out = out) %>% mutate( date_in = dmy(date_in), date_out = dmy(date_out) ) # 生成从最早入住到最晚退房的所有日期 all_days <- seq(min(df$date_in), max(df$date_out), by = "day") # 对每个日期,计算符合「入住≤当天≤退房」的唯一ID数 df2 <- tibble(day = all_days) %>% rowwise() %>% mutate( count = df %>% filter(date_in <= day, date_out >= day) %>% pull(id) %>% n_distinct() ) %>% ungroup() %>% mutate(day = format(day, "%d-%m-%Y"))
验证示例数据
用你给出的两个ID测试,结果完全符合预期:
# 示例数据 sample_df <- data.frame( id = c(1,2), `in` = c("01-01-2020", "05-01-2020"), out = c("08-01-2020", "25-01-2020") ) # 用上面任意一种方法处理后,df2的结果就是: # day count # 01-01-2020 1 # 02-01-2020 1 # 03-01-2020 1 # 04-01-2020 1 # 05-01-2020 2 # ...以此类推,08-01-2020后count变回1直到25-01-2020
注意事项
- 一定要把字符型日期转换成
Date类型,不然没法做日期比较和序列生成 - 如果你的日期格式不是
dd-mm-yyyy,要调整lubridate的转换函数(比如mdy对应月-日-年格式) - 超大数据量的话,可以试试data.table的非等值连接,效率会更高哦
内容的提问来源于stack exchange,提问作者Adrián Valls Carbó
相关产品推荐
相关产品推荐

