根据开始时间和结束时间的差异生成行数(分钟)



这是我在工作中尝试实现的一个真实用例。

Sample data (fake data but similar data structure)
Lap     Starttime     Endtime
1       10:00:00     10:05:00
format: hh:mm:ss
Desired output
Lap     time
1       10:00:00
1       10:01:00
1       10:02:00
1       10:03:00
1       10:04:00
1       10:05:00

到目前为止,我只是在考虑所需的逻辑和技术……代码不正确

import re
import pandas as pd
df = pd.read_csv('sample.csv')

#1.  to determine how many rows to generate. eg. 1000 to 1005 is 6 rows
df['time'] = df['Endtime'] - df['Startime']
#2.  add one new row with 1 added minute. eg. 6 rows
for i in No_of_rows:
if df['time'] < df['Endtime']: #if 'time' still before end time, then continue append
df['time'] = df['Startime'] += 1 #not sure how to select Minute part only 
else:
continue

请原谅我有限的编码技巧。感谢各位专家的帮助。谢谢!

尝试使用pd.date_rangeexplode:

#convert to datetime if needed
df["Starttime"] = pd.to_datetime(df["Starttime"], format="%H:%M:%S")
df["Endtime"] = pd.to_datetime(df["Endtime"], format="%H:%M:%S")
#create list of 1min ranges
df["Range"] = df.apply(lambda x: pd.date_range(x["Starttime"], x["Endtime"], freq="1min"), axis=1)
#explode, drop unneeded columns and keep only time
df = df.drop(["Starttime", "Endtime"], axis=1).explode("Range")
df["Range"] = df["Range"].dt.time
>>> df
Range
Lap          
1    10:00:00
1    10:01:00
1    10:02:00
1    10:03:00
1    10:04:00
1    10:05:00
<编辑>输入df:
df = pd.DataFrame({"Lap": [1],
"Starttime": ["10:00:00"],
"Endtime": ["10:05:00"]}).set_index("Lap")
>>> df
Starttime   Endtime
Lap                    
1    10:00:00  10:05:00

你可以将时间转换为日期时间,将任意预先考虑今天的日期(在什么日期你运行),但是我们可以消除之后,它允许更容易manupulation:

>>> bounds = df[['Starttime', 'Endtime']].transform(pd.to_datetime)
>>> bounds
Starttime             Endtime
0 2021-09-29 10:00:00 2021-09-29 10:05:00
1 2021-09-29 10:00:00 2021-09-29 10:02:00

那么我们可以简单地使用1分钟频率的pd.date_range:

>>> times = bounds.agg(lambda s: pd.date_range(*s, freq='1min'), axis='columns')
>>> times
0    DatetimeIndex(['2021-09-29 10:00:00', '2021-09...
1    DatetimeIndex(['2021-09-29 10:00:00', '2021-09...
dtype: object

现在将其与Lap信息连接并使用df.explode():

>>> result = df[['Lap']].join(times.rename('time')).explode('time').reset_index(drop=True)
>>> result
Lap                time
0    1 2021-09-29 10:00:00
1    1 2021-09-29 10:01:00
2    1 2021-09-29 10:02:00
3    1 2021-09-29 10:03:00
4    1 2021-09-29 10:04:00
5    1 2021-09-29 10:05:00
6    2 2021-09-29 10:00:00
7    2 2021-09-29 10:01:00
8    2 2021-09-29 10:02:00

最后我们想删除日期:

>>> result['time'] = result['time'].dt.time
>>> result
Lap      time
0    1  10:00:00
1    1  10:01:00
2    1  10:02:00
3    1  10:03:00
4    1  10:04:00
5    1  10:05:00
6    2  10:00:00
7    2  10:01:00
8    2  10:02:00

你的系列中的对象现在是datetime.time

这里有另一种不使用apply/agg:

的方法

先转换为日期时间:

df["Starttime"] = pd.to_datetime(df["Starttime"], format="%H:%M:%S")
df["Endtime"] = pd.to_datetime(df["Endtime"], format="%H:%M:%S")

获取结束时间和开始时间之间的差异,然后使用index.repeat,重复行。然后使用groupby &cumcount,在几分钟内pd.to_timedelta并添加到现有的开始时间:

repeats = df['Endtime'].sub(df['Starttime']).dt.total_seconds()//60
out = df.loc[df.index.repeat(repeats+1),['Lap','Starttime']]
out['Starttime'] = (out['Starttime'].add(
pd.to_timedelta(out.groupby("Lap").cumcount(),'min')).dt.time)

print(out)
Lap Starttime
0    1  10:00:00
0    1  10:01:00
0    1  10:02:00
0    1  10:03:00
0    1  10:04:00
0    1  10:05:00

相关内容

  • 没有找到相关文章