Expansión del dataframe de pandas con rango de fechas en columnas.

Tengo un dataframe de pandas con fechas y cadenas similares a esto:

Start End Note Item 2016-10-22 2016-11-05 ZA 2017-02-11 2017-02-25 WB 

Necesito expandirla / transformarla a la siguiente, rellenando las semanas (W-SAT) entre las columnas Inicio y Fin y completando los datos en Nota y Artículos :

 Start Note Item 2016-10-22 ZA 2016-10-29 ZA 2016-11-05 ZA 2017-02-11 WB 2017-02-18 WB 2017-02-25 WB 

¿Cuál es la mejor manera de hacer esto con los pandas? ¿Algún tipo de multi-índice aplica?

Puede iterar sobre cada fila y crear un nuevo dataframe y luego concatenarlos juntos

 pd.concat([pd.DataFrame({'Start': pd.date_range(row.Start, row.End, freq='W-SAT'), 'Note': row.Note, 'Item': row.Item}, columns=['Start', 'Note', 'Item']) for i, row in df.iterrows()], ignore_index=True) Start Note Item 0 2016-10-22 ZA 1 2016-10-29 ZA 2 2016-11-05 ZA 3 2017-02-11 WB 4 2017-02-18 WB 5 2017-02-25 WB 

Si el número de valores únicos de df['End'] - df['Start'] no es demasiado grande, pero el número de filas en su conjunto de datos es grande, entonces la siguiente función será mucho más rápida que recorrer su conjunto de datos:

 def date_expander(dataframe: pd.DataFrame, start_dt_colname: str, end_dt_colname: str, time_unit: str, new_colname: str, end_inclusive: bool) -> pd.DataFrame: td = pd.Timedelta(1, time_unit) # add a timediff column: dataframe['_dt_diff'] = dataframe[end_dt_colname] - dataframe[start_dt_colname] # get the maximum timediff: max_diff = int((dataframe['_dt_diff'] / td).max()) # for each possible timediff, get the intermediate time-differences: df_diffs = pd.concat([pd.DataFrame({'_to_add': np.arange(0, dt_diff + end_inclusive) * td}).assign(_dt_diff=dt_diff * td) for dt_diff in range(max_diff + 1)]) # join to the original dataframe data_expanded = dataframe.merge(df_diffs, on='_dt_diff') # the new dt column is just start plus the intermediate diffs: data_expanded[new_colname] = data_expanded[start_dt_colname] + data_expanded['_to_add'] # remove start-end cols, as well as temp cols used for calculations: data_expanded = data_expanded.drop(columns=[start_dt_colname, end_dt_colname, '_to_add', '_dt_diff']) # don't modify dataframe in place: del dataframe['_dt_diff'] return data_expanded