Saya memiliki dataFrame yang berisi beberapa data penjadwalan ruangan. Berikut adalah contoh data untuk beberapa entri pertama untuk Kamis dan Jumat pagi: hari begin_time end_time 0 R 09:00 10: ...

1
Henry Ecker 5 April 2021, 21:12

3 jawaban

Jawaban Terbaik

Buat bingkai data dari semua interval 15 menit untuk setiap hari (irama janji temu). Maka kita dapat menggunakan np.braodcasting untuk melihat berapa banyak pengguna yang menggunakan kamar di timem yang diberikan untuk setiap hari.

import pandas as pd
import numpy as np

# Convert your times to a numeric type. 
for col in ['BEGIN_TIME', 'END_TIME']:
    df[col] = pd.to_datetime(df[col])
    df[col] = df[col] - df[col].dt.normalize()

# 15-min blocks Monday-Friday
df1 = (pd.concat([pd.DataFrame({'Time': pd.timedelta_range('00:00:00', '23:45:00', freq='15min')})]*5,
                 keys=list('MTWRF'), names=['Days', 'to_drop'])
         .reset_index()
         .drop(columns='to_drop'))
    
# For each day determine the overlap
l = []
for day, gp in df1.groupby('Days'):
    gp['users'] = ((gp['Time'].to_numpy() >= df.loc[df.DAYS.eq(day), 'BEGIN_TIME'].to_numpy()[:, None])
                     & (gp['Time'].to_numpy() <= df.loc[df.DAYS.eq(day), 'END_TIME'].to_numpy()[:, None])).sum(axis=0)
    l.append(gp['users'])

# Join the results back to our 15 minute skeleton
df1 = pd.concat([df1, pd.concat(l)], axis=1)

#Check and see the times on Thursday
df1.loc[df1.Days.eq('R') & df1.Time.between('07:00:00', '14:00:00')]

    Days            Time  users
316    R 0 days 07:00:00      0
317    R 0 days 07:15:00      0
318    R 0 days 07:30:00      0
319    R 0 days 07:45:00      0
320    R 0 days 08:00:00      0
321    R 0 days 08:15:00      0
322    R 0 days 08:30:00      1
323    R 0 days 08:45:00      1
324    R 0 days 09:00:00      2
325    R 0 days 09:15:00      2
326    R 0 days 09:30:00      2
327    R 0 days 09:45:00      2
328    R 0 days 10:00:00      1
329    R 0 days 10:15:00      1
330    R 0 days 10:30:00      0
331    R 0 days 10:45:00      0
332    R 0 days 11:00:00      0
333    R 0 days 11:15:00      0
334    R 0 days 11:30:00      2
335    R 0 days 11:45:00      2
336    R 0 days 12:00:00      2
337    R 0 days 12:15:00      2
338    R 0 days 12:30:00      1
339    R 0 days 12:45:00      1
340    R 0 days 13:00:00      0
341    R 0 days 13:15:00      0
342    R 0 days 13:30:00      0
343    R 0 days 13:45:00      0
344    R 0 days 14:00:00      0
1
ALollz 5 April 2021, 18:44

Algoritma kode psuedo untuk ini, mengingat Anda memiliki dataset yang relatif kecil, bisa menjadi sesuatu seperti ini.

collisions = dict()  # {room: [(collision_start, collision_end)]}
for each reservation R1:
    for each other reservation R2 where R2.room=R1.room:
        if R2.end_time > R1.start_time and R2.start_time < R1.end_time:
            # COLLISION... you need to edit code below to make sure key exists
            collisions[R].append((start_of_collision, end_of_collision))

Untuk menentukan start_of_collision dan end_of_collision akan membutuhkan sedikit lebih banyak pekerjaan, karena Anda perlu memeriksa 3 kasus.

  • Kasus 1: R1 Mulai sebelum R2 Mulai, dan berakhir sebelum R2 berakhir.

    (start_of_collision, end_of_collision) = (R2.start, R1.end)
    
  • Kasus 2: R1 Mulai setelah R2 Mulai, dan berakhir sebelum R2 berakhir.

    (start_of_collision, end_of_collision) = (R1.start, R1.end)
    
  • Kasus 3: R1 Mulai setelah R2 Mulai, dan berakhir setelah R2 berakhir.

    (start_of_collision, end_of_collision) = (R1.start, R2.end)
    
0
Frank Bryce 5 April 2021, 18:28

Sepertinya saya cara yang tepat untuk melakukan ini adalah memformat ulang data Anda sehingga Anda memiliki serangkaian acara (baik 'mulai' atau 'end'), dengan kolom Tanggal Tanggal. Anda kemudian dapat mengurutkan berdasarkan timestamp, dan melakukan penghitung sederhana:

import pandas as pd

df = pd.DataFrame({'DAYS': {0: 'R', 1: 'R', 2: 'R', 3: 'R', 4: 'F', 5: 'F', 6: 'F'},
                   'BEGIN_TIME': {0: '09:00', 1: '08:30', 2: '11:30', 3: '11:30', 4: '08:00', 5: '07:00', 6: '08:00'},
                   'END_TIME': {0: '10:15', 1: '09:45', 2: '12:20', 3: '12:45', 4: '10:30', 5: '08:15', 6: '10:30'}}
                  )

days="MTWRF"

# Convert to DateTime
df["BEGIN_TIME"] = df["BEGIN_TIME"].astype("datetime64[ns]")
df["END_TIME"] = df["END_TIME"].astype("datetime64[ns]")

# Convert to a more useful format.

newdata = []
for row in df.iterrows():
    row = row[1]
    newdata.append((
        row["DAYS"],
        "start",
        row["BEGIN_TIME"]
    ))
    newdata.append((
        row["DAYS"],
        "end",
        row["END_TIME"]
    ))
newdata.sort(key=lambda r: (days.index(r[0]),r[2]))
print(newdata)

count = 0
for row in newdata:
    if row[1] == 'start':
        count += 1
    else:
        count -= 1
    print( row[0], row[2].strftime("%H:%M"), count )

Output tidak persis seperti yang Anda inginkan, tetapi mudah-mudahan Anda dapat melihat cara ke sana dari sini.

R 08:30 1   
R 09:00 2   
R 09:45 1   
R 10:15 0   
R 11:30 1   
R 11:30 2   
R 12:20 1   
R 12:45 0   
F 07:00 1   
F 08:00 2   
F 08:00 3   
F 08:15 2   
F 10:30 1   
F 10:30 0   
0
Tim Roberts 5 April 2021, 18:25