Convert components to a join table with columns id1, id2
    Args:
        components: A collection of components, each of which is a set of vertex ids.
            If a dictionary, then the key is the id for the component. Otherwise,
            the component id is determined by applying id_func to the component.
        id_func: If components is a dictionary, this should be None. Otherwise,
            this is a callable that, given a set of vertices, deermines the id.
            If components is not a dict and id_func is None, it defaults to `min`.
    Returns: A dataframe representing the one-to-many relationship between
            component names (id1) and their members (id2).

def components_to_df(components, id_func=None):
    """
    Convert components to a join table with columns id1, id2
    Args:
        components: A collection of components, each of which is a set of vertex ids.
            If a dictionary, then the key is the id for the component. Otherwise,
            the component id is determined by applying id_func to the component.
        id_func: If components is a dictionary, this should be None. Otherwise,
            this is a callable that, given a set of vertices, deermines the id.
            If components is not a dict and id_func is None, it defaults to `min`.
    Returns: A dataframe representing the one-to-many relationship between
            component names (id1) and their members (id2).
    """
    deduped = np.empty((0, 2), dtype=int)

    if id_func is None:
        if isinstance(components, dict):
            raise ValueError("If components is a dict, id_func should be None.")
        else:
            id_func = min

    for c in components:
        if id_func is None:
            id1 = c
            c = components[c]
        else:
            id1 = id_func(c)

        deduped = np.append(deduped, [[id1, id2] for id2 in c], axis=0)

    deduped = pd.DataFrame(deduped, columns=['id1', 'id2'])
    return deduped