<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:

def create_agg_ctable(self, groupby_cols, agg_list, expectedlen, rootdir):
        '''Create a container for the output table, a dictionary describing it's
            columns and a list of tuples describing aggregation
            operations to perform.

        Args:
            groupby_cols (list): a list of columns to groupby over
            agg_list (list): the aggregation operations (see groupby for more info)
            expectedlen (int): expected length of output table
            rootdir (string): the directory to write the table to

        Returns:
            ctable: A table in the correct format for containing the output of
                    the specified aggregation operations.
            dict: (dtype_dict) dictionary describing columns to create
            list: (agg_ops) list of tuples of the form:
                    (input_col_name, output_col_name, agg_op)
                    input_col_name (string): name of the column to act on
                    output_col_name (string): name of the column to output to
                    agg_op (int): aggregation operation to perform
        '''
        dtype_dict = {}

        # include all the groupby columns
        for col in groupby_cols:
            dtype_dict[col] = self[col].dtype

        agg_ops_list = ['sum', 'count', 'count_distinct', 'sorted_count_distinct', 'mean', 'std']
        agg_ops = []

        for agg_info in agg_list:

            if not isinstance(agg_info, list):
                # example: ['m1', 'm2', ...]
                # default operation (sum) and default output column name (same is input)
                output_col_name = agg_info
                input_col_name = agg_info
                agg_op = 'sum'
            else:
                input_col_name = agg_info[0]
                agg_op = agg_info[1]

                if len(agg_info) == 2:
                    # example: [['m1', 'sum'], ['m2', 'mean], ...]
                    # default output column name
                    output_col_name = input_col_name
                else:
                    # example: [['m1', 'sum', 'mnew1'], ['m1, 'mean','mnew2'], ...]
                    # fully specified
                    output_col_name = agg_info[2]

            if agg_op not in agg_ops_list:
                raise NotImplementedError(
                    'Unknown Aggregation Type: ' + str(agg_op))

            # choose output column dtype based on aggregation operation and
            # input column dtype
            # TODO: check if the aggregation columns is numeric
            # NB: we could build a concatenation for strings like pandas, but I would really prefer to see that as a
            # separate operation
            if agg_op in ('count', 'count_distinct', 'sorted_count_distinct'):
                output_col_dtype = np.dtype(np.int64)
            elif agg_op in ('mean', 'std'):
                output_col_dtype = np.dtype(np.float64)
            else:
                output_col_dtype = self[input_col_name].dtype

            dtype_dict[output_col_name] = output_col_dtype

            # save output
            agg_ops.append((input_col_name, output_col_name, agg_op))

        # create aggregation table
        ct_agg = bcolz.ctable(
            np.zeros(expectedlen, [('tmp_col_bquery__', np.bool)]),
            expectedlen=expectedlen,
            rootdir=rootdir)

        return ct_agg, dtype_dict, agg_ops