def explode(df, lst_cols, fill_value='', preserve_index=False):
if (lst_cols is not None
and len(lst_cols) > 0
and not isinstance(lst_cols, (list, tuple, np.ndarray, pd.Series))):
lst_cols = [lst_cols]
idx_cols = df.columns.difference(lst_cols)
lens = df[lst_cols[0]].str.len()
idx = np.repeat(df.index.values, lens)
res = (pd.DataFrame({
col:np.repeat(df[col].values, lens)
for col in idx_cols},
index=idx)
.assign(**{col:np.concatenate(df.loc[lens>0, col].values)
for col in lst_cols}))
if (lens == 0).any():
res = (res.append(df.loc[lens==0, idx_cols], sort=False)
.fillna(fill_value))
res = res.sort_index()
if not preserve_index:
res = res.reset_index(drop=True)
return res