docs: def make_group_index(self, groupby_cols, bool_arr):
          '''Create unique groups for groupby loop
  
              Args:
                  factor_list:
                  values_list:
                  groupby_cols:
                  bool_arr:
  
              Returns:
                  carray: (carray_factor)
                  int: (nr_groups) the number of resulting groups
                  int: (skip_key)
          '''
          factor_list, values_list = self.factorize_groupby_cols(groupby_cols)
  
          # create unique groups for groupby loop
          if len(factor_list) == 0:
              # no columns to groupby over, so directly aggregate the measure
              # columns to 1 total
              tmp_rootdir = self.create_tmp_rootdir()
              carray_factor = bcolz.zeros(len(self), dtype='int64', rootdir=tmp_rootdir, mode='w')
              carray_values = ['Total']
          elif len(factor_list) == 1:
              # single column groupby, the groupby output column
              # here is 1:1 to the values
              carray_factor = factor_list[0]
              carray_values = values_list[0]
          else:
              # multi column groupby
              # first combine the factorized columns to single values
              if self.group_cache_valid(col_list=groupby_cols):
                  # there is a group cache that we can use
                  col_rootdir = os.path.join(self.rootdir, self.create_group_base_name(groupby_cols))
                  col_factor_rootdir = col_rootdir + '.factor'
                  carray_factor = bcolz.carray(rootdir=col_factor_rootdir)
                  col_values_rootdir = col_rootdir + '.values'
                  carray_values = bcolz.carray(rootdir=col_values_rootdir)
              else:
                  # create a brand new groupby col combination
                  carray_factor, carray_values = \
                      self.create_group_column_factor(factor_list, groupby_cols, cache=self.auto_cache)
  
          nr_groups = len(carray_values)
          skip_key = None
  
          if bool_arr is not None:
              # make all non relevant combinations -1
              tmp_rootdir = self.create_tmp_rootdir()
              carray_factor = bcolz.eval(
                  '(factor + 1) * bool - 1',
                  user_dict={'factor': carray_factor, 'bool': bool_arr}, rootdir=tmp_rootdir, mode='w')
              # now check how many unique values there are left
              tmp_rootdir = self.create_tmp_rootdir()
              labels = bcolz.carray([], dtype='int64', expectedlen=len(carray_factor), rootdir=tmp_rootdir, mode='w')
              carray_factor, values = ctable_ext.factorize(carray_factor, labels)
              # values might contain one value too much (-1) (no direct lookup
              # possible because values is a reversed dict)
              filter_check = \
                  [key for key, value in values.items() if value == -1]
              if filter_check:
                  skip_key = filter_check[0]
              # the new nr of groups depends on the outcome after filtering
              nr_groups = len(values)
  
          # using nr_groups as a total length might be one one off due to the skip_key
          # (skipping a row in aggregation)
          # but that is okay normally
  
          if skip_key is None:
              # if we shouldn't skip a row, set it at the first row after the total number of groups
              skip_key = nr_groups
  
          return carray_factor, nr_groups, skip_key