【问题标题】:Duplicate rows with a new column具有新列的重复行
【发布时间】:2022-01-25 19:59:58
【问题描述】:

所以我有一个这样的数据框

df1 = {'id':[123,347],
   'shift_start':['2022-01-25 09:00:00', '2022-01-28 19:00:00'],
   'shift_end':['2022-01-25 12:30:00', '2022-01-29 00:00:00']}

df1 = pd.DataFrame(df1,columns=['id','shift_start', 'shift_end'])
id  shift_start         shift_end
123 2022-01-25 09:00:00 2022-01-28 12:30:00
347 2022-01-25 23:00:00 2022-01-29 00:00:00

我想为每个 id 获取每个班次中有多少个 30 分钟的时段,所以像这样

id  shift_start         shift_end           slot_start          slot_end
123 2022-01-25 09:00:00 2022-01-28 12:30:00 2022-01-25 09:00:00 2022-01-25 09:30:00
123 2022-01-25 09:00:00 2022-01-28 12:30:00 2022-01-25 09:30:00 2022-01-25 10:00:00
123 2022-01-25 09:00:00 2022-01-28 12:30:00 2022-01-25 10:00:00 2022-01-25 10:30:00
123 2022-01-25 09:00:00 2022-01-28 12:30:00 2022-01-25 10:30:00 2022-01-25 11:00:00
123 2022-01-25 09:00:00 2022-01-28 12:30:00 2022-01-25 11:00:00 2022-01-25 11:30:00
123 2022-01-25 09:00:00 2022-01-28 12:30:00 2022-01-25 11:30:00 2022-01-25 12:00:00
123 2022-01-25 09:00:00 2022-01-28 12:30:00 2022-01-25 12:00:00 2022-01-25 12:30:00
347 2022-01-25 23:00:00 2022-01-29 00:00:00 2022-01-25 23:00:00 2022-01-29 23:30:00
347 2022-01-25 23:00:00 2022-01-29 00:00:00 2022-01-25 23:30:00 2022-01-29 00:00:00

我找到了找到 30 分钟插槽的方法,但我仍然找不到将它们添加到数据帧中的方法

def datetime_range(start, end, delta):
    current = start
    while current < end:
        yield current
        current += delta

for index, row in df1.iterrows():
    dts = [dt.strftime('%Y-%m-%d %H:%M:%S') for dt in
        datetime_range(datetime(row['shift_start'].year, row['shift_start'].month, row['shift_start'].day, row['shift_start'].hour, row['shift_start'].minute),
                       datetime(row['shift_end'].year, row['shift_end'].month, row['shift_end'].day, row['shift_end'].hour, row['shift_end'].minute),
        timedelta(minutes=30))]

    print(dts)

非常欢迎任何帮助。谢谢!

【问题讨论】:

    标签: python-3.x pandas date datetime


    【解决方案1】:

    这是一种方法:

    slots = df1[['shift_start', 'shift_end']]
        .apply(lambda x: pd.date_range(*x, freq='30min'), axis=1)
        .explode()
        .rename('slot_start')
        .to_frame()
    
    slots['slot_end'] = slots['slot_start'].shift(-1)
    
    df1 = pd.concat([df1, slots], axis=1).dropna()
    df1 = df1[(df1.shift_end >= df1.slot_end)]                                                     
    

    输出:

       id          shift_start            shift_end          slot_start            slot_end
    0  123  2022-01-25 09:00:00  2022-01-25 12:30:00 2022-01-25 09:00:00 2022-01-25 09:30:00
    0  123  2022-01-25 09:00:00  2022-01-25 12:30:00 2022-01-25 09:30:00 2022-01-25 10:00:00
    0  123  2022-01-25 09:00:00  2022-01-25 12:30:00 2022-01-25 10:00:00 2022-01-25 10:30:00
    0  123  2022-01-25 09:00:00  2022-01-25 12:30:00 2022-01-25 10:30:00 2022-01-25 11:00:00
    0  123  2022-01-25 09:00:00  2022-01-25 12:30:00 2022-01-25 11:00:00 2022-01-25 11:30:00
    0  123  2022-01-25 09:00:00  2022-01-25 12:30:00 2022-01-25 11:30:00 2022-01-25 12:00:00
    0  123  2022-01-25 09:00:00  2022-01-25 12:30:00 2022-01-25 12:00:00 2022-01-25 12:30:00
    1  347  2022-01-28 19:00:00  2022-01-29 00:00:00 2022-01-28 19:00:00 2022-01-28 19:30:00
    1  347  2022-01-28 19:00:00  2022-01-29 00:00:00 2022-01-28 19:30:00 2022-01-28 20:00:00
    1  347  2022-01-28 19:00:00  2022-01-29 00:00:00 2022-01-28 20:00:00 2022-01-28 20:30:00
    1  347  2022-01-28 19:00:00  2022-01-29 00:00:00 2022-01-28 20:30:00 2022-01-28 21:00:00
    1  347  2022-01-28 19:00:00  2022-01-29 00:00:00 2022-01-28 21:00:00 2022-01-28 21:30:00
    1  347  2022-01-28 19:00:00  2022-01-29 00:00:00 2022-01-28 21:30:00 2022-01-28 22:00:00
    1  347  2022-01-28 19:00:00  2022-01-29 00:00:00 2022-01-28 22:00:00 2022-01-28 22:30:00
    1  347  2022-01-28 19:00:00  2022-01-29 00:00:00 2022-01-28 22:30:00 2022-01-28 23:00:00
    1  347  2022-01-28 19:00:00  2022-01-29 00:00:00 2022-01-28 23:00:00 2022-01-28 23:30:00
    1  347  2022-01-28 19:00:00  2022-01-29 00:00:00 2022-01-28 23:30:00 2022-01-29 00:00:00
    

    【讨论】:

    • 谢谢,几乎成功了,只有一个不正确的行 123 2022-01-25 09:00:00 2022-01-25 12:30:00 2022-01-25 12:30 :00 2022-01-28 19:00:00 也许这样的事情应该可以解决问题 df1 = df1[df1.slot_start != df1.shift_end]
    • 我的错,错过了。最后可能更容易过滤,我添加了一个 sn-p。
    • 实际上,这并不能解决所有问题,因为班次开始时间是 7:00 而不是 23:00?我们也有额外的行。我们也可以在 13:00 开始轮班时使用相同的 id,因此它将在 12:30 到 13:00 之间空闲,并且在 13:00 开始另一个轮班。它需要再调整一点。
    • 在做了一些测试之后,我认为使用我上面发布的解决方案应该可以解决问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-25
    • 1970-01-01
    • 1970-01-01
    • 2021-10-04
    • 1970-01-01
    • 2017-05-18
    • 2020-10-01
    相关资源
    最近更新 更多