def aggregate(self, out_file: str = None, select: np.ndarray = None, group_by: Union[str, np.ndarray] = "<STR_LIT>", aggr_by: str = "<STR_LIT>", aggr_ca_by: Dict[str, str] = None) -> np.ndarray:
ca = {}  <EOL>if select is not None:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>if isinstance(group_by, np.ndarray):<EOL><INDENT>labels = group_by<EOL><DEDENT>else:<EOL><INDENT>labels = (self.ca[group_by]).astype('<STR_LIT:int>')<EOL><DEDENT>_, zero_strt_sort_noholes_lbls = np.unique(labels, return_inverse=True)<EOL>n_groups = len(set(labels))<EOL>if aggr_ca_by is not None:<EOL><INDENT>for key in self.ca.keys():<EOL><INDENT>if key not in aggr_ca_by:<EOL><INDENT>continue<EOL><DEDENT>func = aggr_ca_by[key]<EOL>if func == "<STR_LIT>":<EOL><INDENT>for val in set(self.ca[key]):<EOL><INDENT>if np.issubdtype(type(val), np.str_):<EOL><INDENT>valnew = val.replace("<STR_LIT:/>", "<STR_LIT:->")  <EOL>valnew = valnew.replace("<STR_LIT:.>", "<STR_LIT:_>")  <EOL><DEDENT>ca[key + "<STR_LIT:_>" + str(valnew)] = npg.aggregate(zero_strt_sort_noholes_lbls, (self.ca[key] == val).astype('<STR_LIT:int>'), func="<STR_LIT>", fill_value=<NUM_LIT:0>)<EOL><DEDENT><DEDENT>elif func == "<STR_LIT>":<EOL><INDENT>def mode(x):  <EOL><INDENT>return scipy.stats.mode(x)[<NUM_LIT:0>][<NUM_LIT:0>]<EOL><DEDENT>ca[key] = npg.aggregate(zero_strt_sort_noholes_lbls, self.ca[key], func=mode, fill_value=<NUM_LIT:0>).astype('<STR_LIT:str>')<EOL><DEDENT>elif func == "<STR_LIT>":<EOL><INDENT>ca[key] = npg.aggregate(zero_strt_sort_noholes_lbls, self.ca[key], func=func, fill_value=<NUM_LIT:0>)<EOL><DEDENT>elif func == "<STR_LIT>":<EOL><INDENT>ca[key] = npg.aggregate(zero_strt_sort_noholes_lbls, self.ca[key], func=func, fill_value=self.ca[key][<NUM_LIT:0>])<EOL><DEDENT><DEDENT><DEDENT>m = np.empty((self.shape[<NUM_LIT:0>], n_groups))<EOL>for (_, selection, view) in self.scan(axis=<NUM_LIT:0>, layers=["<STR_LIT>"]):<EOL><INDENT>vals_aggr = npg.aggregate(zero_strt_sort_noholes_lbls, view[:, :], func=aggr_by, axis=<NUM_LIT:1>, fill_value=<NUM_LIT:0>)<EOL>m[selection, :] = vals_aggr<EOL><DEDENT>if out_file is not None:<EOL><INDENT>loompy.create(out_file, m, self.ra, ca)<EOL><DEDENT>return m<EOL>
Aggregate the Loom file by applying aggregation functions to the main matrix as well as to the column attributes

Args:
        out_file	The name of the output Loom file (will be appended to if it exists)
        select		Bool array giving the columns to include (or None, to include all)
        group_by	The column attribute to group by, or an np.ndarray of integer group labels
        aggr_by 	The aggregation function for the main matrix
        aggr_ca_by	A dictionary of aggregation functions for the column attributes (or None to skip)

Returns:
        m			Aggregated main matrix

Remarks:
        aggr_by gives the aggregation function for the main matrix
        aggr_ca_by is a dictionary with column attributes as keys and aggregation functionas as values

        Aggregation functions can be any valid aggregation function from here: https://github.com/ml31415/numpy-groupies

        In addition, you can specify:
                "tally" to count the number of occurences of each value of a categorical attribute