如何在Pandas中复制行并生成FROM到TO的分钟时间序列列
在Pandas中生成分钟级时间序列并复制DataFrame行
我明白你想要实现的需求——把原DataFrame的每一行按照FROM到TO的分钟间隔展开,同时保留原有的ID、FROM、TO列,新增time列来存放每个分钟点。你已经在R里用data.table实现了,我来给你对应Python Pandas的解决方案。
先明确你的输入输出示例:
输入DataFrame
ID FROM TO A 15:30 15:33 B 16:40 16:44 C 15:20 15:22
期望输出DataFrame
ID FROM TO time A 15:30 15:33 15:30 A 15:30 15:33 15:31 A 15:30 15:33 15:32 A 15:30 15:33 15:33 B 16:40 16:44 16:40 B 16:40 16:44 16:41 B 16:40 16:44 16:42 B 16:40 16:44 16:43 B 16:40 16:44 16:44 C 15:20 15:22 15:20 C 15:20 15:22 15:21 C 15:20 15:22 15:22
方法一:apply + pd.date_range + explode(直观贴近R思路)
这种方式逻辑和你R中的实现非常相似,先逐行生成时间序列,再展开列表:
import pandas as pd # 构造输入数据 df = pd.DataFrame({ 'ID': ['A', 'B', 'C'], 'FROM': ['15:30', '16:40', '15:20'], 'TO': ['15:33', '16:44', '15:22'] }) # 将字符串转为时间类型(默认会带日期,后续可转回时分格式) df['FROM'] = pd.to_datetime(df['FROM'], format='%H:%M') df['TO'] = pd.to_datetime(df['TO'], format='%H:%M') # 对每行生成FROM到TO的分钟级时间序列,存为列表 df['time'] = df.apply(lambda row: pd.date_range(start=row['FROM'], end=row['TO'], freq='min'), axis=1) # 炸开time列的列表,生成多行数据 new_df = df.explode('time', ignore_index=True) # 把时间列转回时分字符串格式(和输入格式统一) new_df[['FROM', 'TO', 'time']] = new_df[['FROM', 'TO', 'time']].apply(lambda x: x.dt.strftime('%H:%M')) print(new_df)
方法二:向量化实现(大数据量更高效)
如果你的数据集很大,apply的逐行处理效率可能偏低,这种向量化方式性能更好:
import pandas as pd df = pd.DataFrame({ 'ID': ['A', 'B', 'C'], 'FROM': ['15:30', '16:40', '15:20'], 'TO': ['15:33', '16:44', '15:22'] }) # 转换时间类型 df['FROM'] = pd.to_datetime(df['FROM'], format='%H:%M') df['TO'] = pd.to_datetime(df['TO'], format='%H:%M') # 计算每行需要生成的时间点数量 df['n_points'] = (df['TO'] - df['FROM']).dt.total_seconds() // 60 + 1 # 按重复次数展开行 df_expanded = df.loc[df.index.repeat(df['n_points'])] # 计算每个行组内的分钟偏移量 df_expanded['offset'] = df_expanded.groupby(df_expanded.index).cumcount() # 生成time列 df_expanded['time'] = df_expanded['FROM'] + pd.to_timedelta(df_expanded['offset'], unit='min') # 整理列并格式化时间 new_df = df_expanded[['ID', 'FROM', 'TO', 'time']].reset_index(drop=True) new_df[['FROM', 'TO', 'time']] = new_df[['FROM', 'TO', 'time']].apply(lambda x: x.dt.strftime('%H:%M')) print(new_df)
两种方法都能得到你需要的结果,按需选择即可。
内容的提问来源于stack exchange,提问作者user2552108
相关产品推荐
相关产品推荐

