基于进出时间数据集逐小时统计区域存量的技术问询
嘿,我来帮你搞定这个逐小时统计区域存量的需求!这里有两种实用的实现方式,既可以在原数据集上扩展满足你的优先要求,也能生成独立的统计结果,用Python的pandas处理起来非常顺畅。
第一步:准备数据与基础转换
首先我们把给定的数据集读入,然后给原数据新增两个关键列:Arrival_Hour(用户进入时间对应的小时数,从2000-01-01 00:00开始计算)和Exit_Hour(用户离开时间对应的小时数)。这一步是为了快速定位每个用户覆盖的小时区间。
import pandas as pd # 加载你的数据集 df = pd.DataFrame({ 'ID': [7656, 7657, 7658, 7659, 7660], 'Arrival (sec)': [152845.085, 152845.085, 147617, 152852.811, 147617], 'Exit (sec)': [155747.92, 155784.91, 150035.747, 158216.428, 150076.503] }) # 计算进入/离开对应的小时数(秒数整除3600,得到从起始点开始的小时序号) df['Arrival_Hour'] = df['Arrival (sec)'].floordiv(3600).astype(int) df['Exit_Hour'] = df['Exit (sec)'].floordiv(3600).astype(int)
此时原数据集新增列后,截取部分内容如下:
ID Arrival (sec) Exit (sec) Arrival_Hour Exit_Hour
7656 152845.085 155747.92 42 43
7657 152845.085 155784.91 42 43
...
方式一:在原数据集扩展后统计(优先满足需求)
我们可以给原数据集新增Covered_Hours列,把每个用户覆盖的所有小时都列出来,再通过展开分组来统计每个小时的存量。
# 生成每个用户覆盖的小时列表(从进入小时到离开小时的所有整数小时) df['Covered_Hours'] = df.apply(lambda row: list(range(row['Arrival_Hour'], row['Exit_Hour'] + 1)), axis=1) # 展开小时列表,让每个小时对应一条用户记录 expanded_df = df.explode('Covered_Hours') # 按小时分组,统计唯一ID的数量(即该小时的区域存量) hourly_inventory = expanded_df.groupby('Covered_Hours')['ID'].nunique().reset_index(name='Inventory') # 可选:把小时序号转换成具体的日期时间,更直观 hourly_inventory['Datetime'] = pd.to_datetime('2000-01-01') + pd.to_timedelta(hourly_inventory['Covered_Hours'], unit='h')
这样得到的hourly_inventory就是独立的统计数据集,而原数据集df也保留了所有扩展信息。
方式二:直接生成独立统计数据集
如果不需要在原数据集上保留太多扩展信息,可以直接生成所有需要统计的小时区间,逐个计算每个小时的存量。
# 确定需要统计的小时范围:从最早进入小时到最晚离开小时 min_hour = df['Arrival_Hour'].min() max_hour = df['Exit_Hour'].max() hours_range = pd.DataFrame({'Covered_Hours': range(min_hour, max_hour + 1)}) # 定义函数:计算单个小时内的区域存量 def count_inventory(hour): hour_start = hour * 3600 hour_end = (hour + 1) * 3600 # 只要用户进入时间早于小时结束,且离开时间晚于小时开始,就属于该小时的存量 return len(df[(df['Arrival (sec)'] < hour_end) & (df['Exit (sec)'] > hour_start)]) # 应用函数到每个小时 hours_range['Inventory'] = hours_range['Covered_Hours'].apply(count_inventory) # 同样可以转换为直观的日期时间 hours_range['Datetime'] = pd.to_datetime('2000-01-01') + pd.to_timedelta(hours_range['Covered_Hours'], unit='h')
结果说明
两种方式得到的统计结果是一致的,针对你的数据集,统计出来的部分结果大概是这样:
Covered_Hours Inventory Datetime
41 2 2000-01-02 17:00:00
42 4 2000-01-02 18:00:00
43 3 2000-01-02 19:00:00
44 1 2000-01-02 20:00:00
这里的逻辑是:统计每个小时时间段内,任何时刻处于区域内的用户数量,只要用户的停留时间和该小时有重叠,就会被计入。
内容的提问来源于stack exchange,提问作者Christian R. Houen

