Question: I have a Pandas DataFrame representing timesheets with start and end times, as well as optional rest and meal break intervals. My goal is to expand a single row into multiple rows with correct intervals. It's worth noting that:  A timesheet might not have any breaks. A timesheet might have only a rest break, only a meal break, or both. The order of meal and rest breaks can vary (meal break can be both before and after rest break).  Here's an example DataFrame:    Id Start Time End Time Rest Break Start Time Rest Break End Time Meal Break Start Time Meal Break End Time     1 2024-01-26 07:59 2024-01-26 12:33 2024-01-26 10:43 2024-01-26 10:53 2024-01-26 12:03 2024-01-26 12:33   2 2024-01-26 14:29 2024-01-26 17:35 2024-01-26 16:33 2024-01-26 16:44 NaN NaN   3 2024-01-26 08:02 2024-01-26 12:45 NaN NaN NaN NaN   4 2024-01-26 09:15 2024-01-26 16:15 NaN NaN 2024-01-26 12:15 2024-01-26 12:45   5 2024-01-26 09:10 2024-01-26 16:37 2024-01-26 15:43 2024-01-26 15:55 2024-01-26 13:06 2024-01-26 13:37    The output I need:    Id Category Start Time End Time     1 Session 2024-01-26 07:59 2024-01-26 10:43   1 Rest Break 2024-01-26 10:43 2024-01-26 10:53   1 Session 2024-01-26 10:53 2024-01-26 12:03   1 Meal Break 2024-01-26 12:03 2024-01-26 12:33   2 Session 2024-01-26 14:29 2024-01-26 16:33   2 Rest Break 2024-01-26 16:33 2024-01-26 16:44   2 Session 2024-01-26 16:44 2024-01-26 17:35   3 Session 2024-01-26 08:02 2024-01-26 12:45   4 Session 2024-01-26 09:15 2024-01-26 12:15   4 Meal Break 2024-01-26 12:15 2024-01-26 12:45   4 Session 2024-01-26 12:45 2024-01-26 16:15   5 Session 2024-01-26 09:10 2024-01-26 13:06   5 Meal Break 2024-01-26 13:06 2024-01-26 13:37   5 Session 2024-01-26 13:37 2024-01-26 15:43   5 Rest Break 2024-01-26 15:43 2024-01-26 15:55   5 Session 2024-01-26 15:55 2024-01-26 16:37    My current logic involves extracting all unique datetimes from each row, sorting them, and creating intervals. While this approach somewhat works, I'm struggling with assigning a 'Category' column to each interval. import pandas as pd # Your original DataFrame data = {'Id': [1, 2, 3, 4, 5], 'Start Time': ['2024-01-26 07:59', '2024-01-26 14:29', '2024-01-26 08:02', '2024-01-26 09:15', '2024-01-26 09:10'], 'End Time': ['2024-01-26 12:33', '2024-01-26 17:35', '2024-01-26 12:45', '2024-01-26 16:15', '2024-01-26 16:37'], 'Rest Break Start Time': ['2024-01-26 10:43', '2024-01-26 16:33', None, None, '2024-01-26 15:43'], 'Rest Break End Time': ['2024-01-26 10:53', '2024-01-26 16:44', None, None, '2024-01-26 15:55'], 'Meal Break Start Time': ['2024-01-26 12:03', None, None, '2024-01-26 12:15', '2024-01-26 13:06'], 'Meal Break End Time': ['2024-01-26 12:33', None, None, '2024-01-26 12:45', '2024-01-26 13:37']} df = pd.DataFrame(data) # Create an empty DataFrame to store the expanded rows expanded_df = pd.DataFrame(columns=['Id', 'Start Time', 'End Time']) # Iterate through each row of the original DataFrame for index, row in df.iterrows(): id_value = row['Id'] start_time = pd.to_datetime(row['Start Time']) end_time = pd.to_datetime(row['End Time']) # Collect all times times = {start_time, end_time} for column in ['Rest Break Start Time', 'Rest Break End Time', 'Meal Break Start Time', 'Meal Break End Time']: if not pd.isna(row[column]): times.add(pd.to_datetime(row[column])) # Sort the times sorted_times = sorted(times) # Create intervals for i in range(len(sorted_times) - 1): if sorted_times[i] != sorted_times[i + 1]: expanded_df = expanded_df.append({'Id': id_value, 'Start Time': sorted_times[i], 'End Time': sorted_times[i + 1]}, ignore_index=True) # Sort the expanded DataFrame by 'Id' and 'Start Time' expanded_df = expanded_df.sort_values(by=['Id', 'Start Time']).reset_index(drop=True) # Show the result expanded_df  Here is the output: 

Answer: Here is updated version that computes the category by checking the column names for "Start Time"/"End Time": rows = [] for index, row in df.iterrows(): id_value = row["Id"] start_time = pd.to_datetime(row["Start Time"]) end_time = pd.to_datetime(row["End Time"]) # Collect all times times = {(start_time, "Start Time"), (end_time, "End Time")} for column in [ "Rest Break Start Time", "Rest Break End Time", "Meal Break Start Time", "Meal Break End Time", ]: if not pd.isna(row[column]): times.add((pd.to_datetime(row[column]), column)) # Sort the times sorted_times = sorted(times) # Create intervals for i in range(len(sorted_times) - 1): c1 = sorted_times[i][1] if "Start Time" in c1: cat = c1.replace("Start Time", "").strip() or "Session" elif "End Time" in c1: cat = "Session" if sorted_times[i][0] != sorted_times[i + 1][0]: rows.append( { "Id": id_value, "Category": cat, "Start Time": sorted_times[i][0], "End Time": sorted_times[i + 1][0], } ) expanded_df = pd.DataFrame(rows) # Sort the expanded DataFrame by 'Id' and 'Start Time' expanded_df = expanded_df.sort_values(by=["Id", "Start Time"]).reset_index(drop=True) # Show the result print(expanded_df)  Prints:  Id Category Start Time End Time 0 1 Session 2024-01-26 07:59:00 2024-01-26 10:43:00 1 1 Rest Break 2024-01-26 10:43:00 2024-01-26 10:53:00 2 1 Session 2024-01-26 10:53:00 2024-01-26 12:03:00 3 1 Meal Break 2024-01-26 12:03:00 2024-01-26 12:33:00 4 2 Session 2024-01-26 14:29:00 2024-01-26 16:33:00 5 2 Rest Break 2024-01-26 16:33:00 2024-01-26 16:44:00 6 2 Session 2024-01-26 16:44:00 2024-01-26 17:35:00 7 3 Session 2024-01-26 08:02:00 2024-01-26 12:45:00 8 4 Session 2024-01-26 09:15:00 2024-01-26 12:15:00 9 4 Meal Break 2024-01-26 12:15:00 2024-01-26 12:45:00 10 4 Session 2024-01-26 12:45:00 2024-01-26 16:15:00 11 5 Session 2024-01-26 09:10:00 2024-01-26 13:06:00 12 5 Meal Break 2024-01-26 13:06:00 2024-01-26 13:37:00 13 5 Session 2024-01-26 13:37:00 2024-01-26 15:43:00 14 5 Rest Break 2024-01-26 15:43:00 2024-01-26 15:55:00 15 5 Session 2024-01-26 15:55:00 2024-01-26 16:37:00