Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何有效地将(开始时间,[时间增量])转换为(开始时间,结束时间)?_Python_Python 3.x_Pandas - Fatal编程技术网

Python 如何有效地将(开始时间,[时间增量])转换为(开始时间,结束时间)?

Python 如何有效地将(开始时间,[时间增量])转换为(开始时间,结束时间)?,python,python-3.x,pandas,Python,Python 3.x,Pandas,基本上,我有数据提供开始时间、时隙数量和每个时隙的持续时间。 我想把它转换成一个开始时间和结束时间的数据帧——我已经做到了,但我忍不住认为它效率不高,或者说特别像python。 实际数据具有多个ID,因此需要分组 import pandas as pd slots = pd.DataFrame({"ID": 1, "StartDate": pd.to_datetime("2019-01-01 10:30:00"), "Quantity": 3, "Duration": pd.to_timede

基本上,我有数据提供开始时间、时隙数量和每个时隙的持续时间。 我想把它转换成一个开始时间和结束时间的数据帧——我已经做到了,但我忍不住认为它效率不高,或者说特别像python。 实际数据具有多个ID,因此需要分组

import pandas as pd

slots = pd.DataFrame({"ID": 1, "StartDate": pd.to_datetime("2019-01-01 10:30:00"), "Quantity": 3, "Duration": pd.to_timedelta(30, unit="minutes")}, index=[0])
grp_data = slots.groupby("ID")

bob = []

for rota_id, row in grp_data:
    start = row.iloc[0, 1]
    delta = row.iloc[0, 3]
    for quantity in range(1, int(row.iloc[0, 2] + 1)):
        data = {"RotaID":    rota_id,
                "DateStart": start,
                "Duration":  delta,
                "DateEnd":   start+delta}

        bob.append(data)
        start = start + delta

fred = pd.DataFrame(bob)
这可能会在其他地方得到回答,但我不知道如何正确搜索,因为我不确定我的问题是什么

编辑:我已经更新了代码,使其在函数调用方面更加高效,而且速度更快,但我仍然有兴趣知道是否有一种矢量化的方法来实现这一点。

这样如何:

indices_dup = [np.repeat(i, quantity) for i, quantity in enumerate(slots.Quantity.values)]
slots_ext = slots.loc[np.concatenate(indices_dup).ravel(), :]

# Add a counter per ID; used to 'shift' the duration along StartDate
slots_ext['counter'] = slots_ext.groupby('ID').cumcount()

# Calculate DateStart and DateEnd based on counter and Duration
slots_ext['DateStart'] = (slots_ext.counter) * slots_ext.Duration.values + slots_ext.StartDate
slots_ext['DateEnd'] = (slots_ext.counter + 1) * slots_ext.Duration.values + slots_ext.StartDate

slots_ext.loc[:, ['ID', 'DateStart', 'Duration', 'DateEnd']].reset_index(drop=True)
性能
使用

收益率:
旧方法:
289 ms±4.59 ms/循环(7次运行的平均值±标准偏差,每个循环1次)


新方法:
8.13 ms±278µs/循环(7次运行的平均值±标准偏差,每个循环100次)
如果这有助于任何人: 我发现我的数据集每个ID有不同的增量,而@RubenB的初始答案不能处理这些。以下是我基于他/她的代码的最终解决方案:

# RubenB's code
indices_dup = [np.repeat(i, quantity) for i, quantity in enumerate(slots.Quantity.values)]
slots_ext = slots.loc[np.concatenate(indices_dup).ravel(), :]

# Calculate the cumulative sum of the delta per rota ID
slots_ext["delta_sum"] = slots_ext.groupby("ID")["Duration"].cumsum()
slots_ext["delta_sum"] = pd.to_timedelta(slots_ext["delta_sum"], unit="minutes")

# Use the cumulative sum to calculate the running end dates and then the start dates
first_value = slots_ext.StartDate[0]
slots_ext["EndDate"] = slots_ext.delta_sum.values + slots_ext.StartDate
slots_ext["StartDate"] = slots_ext.EndDate.shift(1)
slots_ext.loc[0, "StartDate"] = first_value
slots_ext.reset_index(drop=True, inplace=True)


您是否有一个比对应于“pythonic”代码的问题更具体/更少以观点为中心的问题?请看,坚持一个问题是有效的,只要仍然有实质性的“蟒蛇”标准删除。我已经猜测了剩余的物质是什么,并试图为此进行编辑;您对该编辑的审阅将不胜感激。看起来您正在大量调用
append
。据我所见,
concat
几乎等同于
append
,但它允许您建立一个数据帧列表,然后在一个调用中将它们连接在一起。@charlesduff感谢您的编辑,这正是我想要问的。非常感谢。Pythonic是一个糟糕的表达方式这是一个非常有趣的方式来看待它,虽然我还没有亲自测试它-基于你的基准,这看起来要快得多。非常感谢。
# RubenB's code
indices_dup = [np.repeat(i, quantity) for i, quantity in enumerate(slots.Quantity.values)]
slots_ext = slots.loc[np.concatenate(indices_dup).ravel(), :]

# Calculate the cumulative sum of the delta per rota ID
slots_ext["delta_sum"] = slots_ext.groupby("ID")["Duration"].cumsum()
slots_ext["delta_sum"] = pd.to_timedelta(slots_ext["delta_sum"], unit="minutes")

# Use the cumulative sum to calculate the running end dates and then the start dates
first_value = slots_ext.StartDate[0]
slots_ext["EndDate"] = slots_ext.delta_sum.values + slots_ext.StartDate
slots_ext["StartDate"] = slots_ext.EndDate.shift(1)
slots_ext.loc[0, "StartDate"] = first_value
slots_ext.reset_index(drop=True, inplace=True)