def sort_meta()

in graspologic/plot/plot_matrix.py [0:0]


def sort_meta(length, meta, group, group_order=["size"], item_order=None):
    r"""
    Sort the data and metadata according to the sorting method

    Parameters
    ----------
    length : int
        Number of nodes
    meta : pd.DataFrame, pd.Series, list of pd.Series or np.array, optional
        Metadata of the matrix such as class, cell type, etc., by default None
    group : str, list of str, or array_like, optional
        Attribute in meta to group the graph in the plot, by default None
    group_order : str, list of str, or array_like, optional
        Attribute of the sorting class to sort classes within the graph,
        by default "size"
    item_order : str, list of str, or array_like, optional
        Attribute in meta by which to sort elements within a class, by default None

    Returns
    -------
    inds :
        The index of the data after sorting
    meta :
        The metadata after sorting
    """

    # if metadata does not exist, return the original data
    if meta is None or len(meta) == 0:
        return np.arange(length), meta

    meta = meta.copy()
    # total_sort_by keeps track of what attribute was used to sort
    total_sort_by = []
    # create new columns in the dataframe that correspond to the sorting order
    # one problem with this current sorting algorithm is that we cannot sort
    # classes by size and other class attributes at the same time.

    for gc in group:
        for co in group_order:
            if co == "size":
                class_size = meta.groupby(gc).size()
                # map each node from the sorting class
                # to their sorting class size
                meta[f"{gc}_size_order"] = meta[gc].map(class_size)
                total_sort_by.append(f"{gc}_size_order")
            else:
                class_value = meta.groupby(gc)[co].mean()
                # map each node from the sorting class
                # to certain sorting class attribute
                meta[f"{gc}_{co}_order"] = meta[gc].map(class_value)
                total_sort_by.append(f"{gc}_{co}_order")
        total_sort_by.append(gc)
    total_sort_by += item_order

    # arbitrarily sort the data from 1 to length
    meta["sort_idx"] = range(len(meta))
    # if we actually need to sort, sort by group_order, group, item_order
    if len(total_sort_by) > 0:
        meta.sort_values(total_sort_by, inplace=True, kind="mergesort")

    inds = np.copy(meta["sort_idx"].values)
    meta["sort_idx"] = range(len(meta))
    return inds, meta