df = pd.DataFrame({'A': [('a', 'b'), ('a', 'b'), ('a', 'b'), ('a', 'b')],
    'B': [('c', 'd'), ('c', 'd'), np.nan, np.nan], 'C': [('e', 'f'), ('e',
    'f'), ('e', 'f'), np.nan], 'D': [('g', 'h'), np.nan, np.nan, np.nan]})
df = pd.concat([df] * 1000).reset_index(drop=True)
print(df)

def jez(df):
    stacked = df.stack()
return pd.DataFrame.from_records(stacked.tolist(), index=stacked.index
    ).unstack(1).swaplevel(0, 1, 1).sort_index(1).replace({None: np.nan})
print(df.stack().apply(pd.Series).unstack().swaplevel(0, 1, 1).sort_index(1
    ).replace({None: np.nan}))

def nick(df):
    cols = df.columns.values.tolist()
return pd.concat([df[col].apply(pd.Series) for col in cols], axis=1, keys=cols)

def pir(df):
    df_ = df.stack().unstack(fill_value=tuple([np.nan] * 2))
col = pd.MultiIndex.from_product([df.columns, [0, 1]])
return pd.DataFrame(np.hstack([np.array(s.values.tolist()) for _, s in df_.
    items()]), columns=col)
print(jez(df))
print(nick(df))
print(pir(df))
Python — кадр данных Pandas с кортежами