def aggregate_groups(self, ct_agg, nr_groups, skip_key,
                         carray_factor, groupby_cols, agg_ops,
                         dtype_dict, bool_arr=None):
        '''Perform aggregation and place the result in the given ctable.

        Args:
            ct_agg (ctable): the table to hold the aggregation
            nr_groups (int): the number of groups (number of rows in output table)
            skip_key (int): index of the output row to remove from results (used for filtering)
            carray_factor: the carray for each row in the table a reference to the the unique group index
            groupby_cols: the list of 'dimension' columns that are used to perform the groupby over
            output_agg_ops (list): list of tuples of the form: (input_col, agg_op)
                    input_col (string): name of the column to act on
                    agg_op (int): aggregation operation to perform
            bool_arr: a boolean array containing the filter

        '''

        # this creates the groupby columns
        for col in groupby_cols:

            result_array = ctable_ext.groupby_value(self[col], carray_factor,
                                                    nr_groups, skip_key)

            if bool_arr is not None:
                result_array = np.delete(result_array, skip_key)

            ct_agg.addcol(result_array, name=col)
            del result_array

        # this creates the aggregation columns
        for input_col_name, output_col_name, agg_op in agg_ops:

            input_col = self[input_col_name]
            output_col_dtype = dtype_dict[output_col_name]

            input_buffer = np.empty(input_col.chunklen, dtype=input_col.dtype)
            output_buffer = np.zeros(nr_groups, dtype=output_col_dtype)

            if agg_op == 'sum':
                ctable_ext.aggregate_sum(input_col, carray_factor, nr_groups,
                                         skip_key, input_buffer, output_buffer)
            elif agg_op == 'mean':
                ctable_ext.aggregate_mean(input_col, carray_factor, nr_groups,
                                          skip_key, input_buffer, output_buffer)
            elif agg_op == 'std':
                ctable_ext.aggregate_std(input_col, carray_factor, nr_groups,
                                         skip_key, input_buffer, output_buffer)
            elif agg_op == 'count':
                ctable_ext.aggregate_count(input_col, carray_factor, nr_groups,
                                           skip_key, input_buffer, output_buffer)
            elif agg_op == 'count_distinct':
                ctable_ext.aggregate_count_distinct(input_col, carray_factor, nr_groups,
                                                    skip_key, input_buffer, output_buffer)
            elif agg_op == 'sorted_count_distinct':
                ctable_ext.aggregate_sorted_count_distinct(input_col, carray_factor, nr_groups,
                                                           skip_key, input_buffer, output_buffer)
            else:
                raise KeyError('Unknown aggregation operation ' + str(agg_op))

            if bool_arr is not None:
                output_buffer = np.delete(output_buffer, skip_key)

            ct_agg.addcol(output_buffer, name=output_col_name)
            del output_buffer

        ct_agg.delcol('tmp_col_bquery__')
Perform aggregation and place the result in the given ctable.

        Args:
            ct_agg (ctable): the table to hold the aggregation
            nr_groups (int): the number of groups (number of rows in output table)
            skip_key (int): index of the output row to remove from results (used for filtering)
            carray_factor: the carray for each row in the table a reference to the the unique group index
            groupby_cols: the list of 'dimension' columns that are used to perform the groupby over
            output_agg_ops (list): list of tuples of the form: (input_col, agg_op)
                    input_col (string): name of the column to act on
                    agg_op (int): aggregation operation to perform
            bool_arr: a boolean array containing the filter