如何使用Python为含Key与DateTime列的数据集生成前后1小时的每分钟间隔记录
解决方案:为每条记录生成前后1小时的每分钟时间点
我来帮你搞定这个需求!你的核心目标是基于每条记录的key和唯一datetime,生成该时间点前1小时到原时间、原时间到后1小时两个区间的所有每分钟时间点,对吧?先分析下你现有代码的问题,再给你更高效可靠的实现方式。
原代码的问题
你的思路是对的,但有几个关键问题导致运行异常或效率低下:
- 未确保时间列类型正确:如果原始
datetime列是字符串格式,直接做time-pd.Timedelta会报错,必须先转为datetime64类型。 - 循环
append效率极低:每次fdf.append(timedf)都会创建新的DataFrame,数据量大时会非常卡顿,甚至内存溢出。 - 区间逻辑合并了前后区间:虽然最终结果包含了所需时间点,但如果需要区分“前区间”和“后区间”,原代码无法实现。
高效实现方案
步骤1:预处理数据(确保时间列类型正确)
首先把字符串格式的时间转为datetime类型,这是所有时间运算的基础:
import pandas as pd # 构造你的示例数据(替换成你真实的DataFrame) data = { 'key': ['20181027698', '20181021819', '20181022432'], 'datetime': ['1/17/2018 12:47:00 PM', '1/1/2018 2:20:00 PM', '3/1/2018 11:10 AM'] } df = pd.DataFrame(data) # 转换datetime列为datetime类型 df['datetime'] = pd.to_datetime(df['datetime'])
步骤2:生成带区间类型的时间序列
如果你需要区分每个时间点属于“前区间”还是“后区间”,可以用这个方法:
def generate_time_intervals(row): # 生成前1小时到原时间的区间(包含两端点) start_before = row['datetime'] - pd.Timedelta(hours=1) interval_before = pd.date_range(start_before, row['datetime'], freq='1T') df_before = pd.DataFrame({ 'interval_datetime': interval_before, 'interval_type': 'before' # 标记前区间 }) # 生成原时间到后1小时的区间(包含两端点) end_after = row['datetime'] + pd.Timedelta(hours=1) interval_after = pd.date_range(row['datetime'], end_after, freq='1T') df_after = pd.DataFrame({ 'interval_datetime': interval_after, 'interval_type': 'after' # 标记后区间 }) # 合并两个区间的结果 return pd.concat([df_before, df_after]) # 应用函数并整理结果 result = df.groupby('key').apply(lambda group: generate_time_intervals(group.iloc[0])).reset_index().drop('level_1', axis=1)
步骤3:仅生成合并后的时间序列(无需区分区间)
如果不需要区分区间,只需要所有时间点,可以简化为:
def generate_all_times(row): # 前1小时到原时间 before_range = pd.date_range(row['datetime'] - pd.Timedelta(hours=1), row['datetime'], freq='1T') # 原时间到后1小时 after_range = pd.date_range(row['datetime'], row['datetime'] + pd.Timedelta(hours=1), freq='1T') # 合并并去重(原时间会在两个区间重复) all_times = pd.concat([pd.Series(before_range), pd.Series(after_range)]).drop_duplicates() return all_times # 应用函数并展开结果 result_simple = df.apply(lambda row: pd.Series({ 'key': row['key'], 'interval_datetime': generate_all_times(row) }), axis=1).explode('interval_datetime').reset_index(drop=True)
结果说明
以key=20181027698为例:
- 前区间会包含从
2018-01-17 11:47:00到2018-01-17 12:47:00的61个时间点(包含两端) - 后区间会包含从
2018-01-17 12:47:00到2018-01-17 13:47:00的61个时间点 - 最终结果会自动关联对应的
key,不会出现混乱
这种方法用apply+explode替代循环append,效率提升非常明显,同时解决了时间类型转换的问题,逻辑也更清晰。
内容的提问来源于stack exchange,提问作者user13073332
相关产品推荐
相关产品推荐

