def flatten_nested_df(df: pd.DataFrame, include_prefix: bool=True, seperator: str='_', recursive: bool=True) -> pd.DataFrame:
    'Flatten the lists and dictionaries of the input data frame.\n\n    Parameters\n    ----------\n    df : pd.DataFrame\n        The input data frame\n    include_prefix : bool, optional\n        If True, then it will prefix the new column name with the original column name.\n        Defaults to True.\n    seperator : str, optional\n        The seperator to use between field names when a dictionary is exploded.\n        Defaults to "_".\n    recursive : bool, optional\n        If True, then this will recurse the fields in the data frame. Defaults to True.\n\n    Returns\n    -------\n        pd.DataFrame: The flattened data frame\n    '
    if (seperator is None):
        seperator = '_'
    df = df.reset_index()
    s = (df.applymap(type) == list).all()
    list_columns = s[s].index.tolist()
    s = (df.applymap(type) == dict).all()
    dict_columns = s[s].index.tolist()
    if ((len(list_columns) > 0) or (len(dict_columns) > 0)):
        new_columns = []
        for col in dict_columns:
            expanded = None
            if include_prefix:
                expanded = pd.json_normalize(df[col], sep=seperator).add_prefix(f'{col}{seperator}')
            else:
                expanded = pd.json_normalize(df[col], sep=seperator).add_prefix(f'{seperator}')
            expanded.index = df.index
            df = pd.concat([df, expanded], axis=1).drop(columns=[col])
            new_columns.extend(expanded.columns)
        for col in list_columns:
            df = df.drop(columns=[col]).join(df[col].explode().to_frame())
            new_columns.append(col)
        s = (df[new_columns].applymap(type) == list).all()
        list_columns = s[s].index.tolist()
        s = (df[new_columns].applymap(type) == dict).all()
        dict_columns = s[s].index.tolist()
        if (recursive and ((len(list_columns) > 0) or (len(dict_columns) > 0))):
            df = flatten_nested_df(df, include_prefix=include_prefix, seperator=seperator, recursive=recursive)
    return df
Flatten the lists and dictionaries of the input data frame.

Parameters
----------
df : pd.DataFrame
    The input data frame
include_prefix : bool, optional
    If True, then it will prefix the new column name with the original column name.
    Defaults to True.
seperator : str, optional
    The seperator to use between field names when a dictionary is exploded.
    Defaults to "_".
recursive : bool, optional
    If True, then this will recurse the fields in the data frame. Defaults to True.

Returns
-------
    pd.DataFrame: The flattened data frame
def flatten_nested_df(df: pd.DataFrame, include_prefix: bool=True, seperator: str='_', recursive: bool=True) -> pd.DataFrame:
    'Flatten the lists and dictionaries of the input data frame.\n\n    Parameters\n    ----------\n    df : pd.DataFrame\n        The input data frame\n    include_prefix : bool, optional\n        If True, then it will prefix the new column name with the original column name.\n        Defaults to True.\n    seperator : str, optional\n        The seperator to use between field names when a dictionary is exploded.\n        Defaults to "_".\n    recursive : bool, optional\n        If True, then this will recurse the fields in the data frame. Defaults to True.\n\n    Returns\n    -------\n        pd.DataFrame: The flattened data frame\n    '
    if (seperator is None):
        seperator = '_'
    df = df.reset_index()
    s = (df.applymap(type) == list).all()
    list_columns = s[s].index.tolist()
    s = (df.applymap(type) == dict).all()
    dict_columns = s[s].index.tolist()
    if ((len(list_columns) > 0) or (len(dict_columns) > 0)):
        new_columns = []
        for col in dict_columns:
            expanded = None
            if include_prefix:
                expanded = pd.json_normalize(df[col], sep=seperator).add_prefix(f'{col}{seperator}')
            else:
                expanded = pd.json_normalize(df[col], sep=seperator).add_prefix(f'{seperator}')
            expanded.index = df.index
            df = pd.concat([df, expanded], axis=1).drop(columns=[col])
            new_columns.extend(expanded.columns)
        for col in list_columns:
            df = df.drop(columns=[col]).join(df[col].explode().to_frame())
            new_columns.append(col)
        s = (df[new_columns].applymap(type) == list).all()
        list_columns = s[s].index.tolist()
        s = (df[new_columns].applymap(type) == dict).all()
        dict_columns = s[s].index.tolist()
        if (recursive and ((len(list_columns) > 0) or (len(dict_columns) > 0))):
            df = flatten_nested_df(df, include_prefix=include_prefix, seperator=seperator, recursive=recursive)
    return df