docs: def create_group_column_factor(self, factor_list, groupby_cols, cache=False):
          """
          Create a unique, factorized column out of several individual columns
  
          Parameters
          ----------
          factor_list
          groupby_cols
          cache
  
          Returns
          -------
  
          """
          if not self.rootdir:
              # in-memory scenario
              input_rootdir = None
              col_rootdir = None
              col_factor_rootdir = None
              col_values_rootdir = None
              col_factor_rootdir_tmp = None
              col_values_rootdir_tmp = None
          else:
              # temporary
              input_rootdir = tempfile.mkdtemp(prefix='bcolz-')
              col_factor_rootdir_tmp = tempfile.mkdtemp(prefix='bcolz-')
              col_values_rootdir_tmp = tempfile.mkdtemp(prefix='bcolz-')
  
          # create combination of groupby columns
          group_array = bcolz.zeros(0, dtype=np.int64, expectedlen=len(self), rootdir=input_rootdir, mode='w')
          factor_table = bcolz.ctable(factor_list, names=groupby_cols)
          ctable_iter = factor_table.iter(outcols=groupby_cols, out_flavor=tuple)
          ctable_ext.create_group_index(ctable_iter, len(groupby_cols), group_array)
  
          # now factorize the results
          carray_factor = \
              bcolz.carray([], dtype='int64', expectedlen=self.size, rootdir=col_factor_rootdir_tmp, mode='w')
          carray_factor, values = ctable_ext.factorize(group_array, labels=carray_factor)
          carray_factor.flush()
  
          carray_values = \
              bcolz.carray(np.fromiter(values.values(), dtype=np.int64), rootdir=col_values_rootdir_tmp, mode='w')
          carray_values.flush()
  
          del group_array
          if cache:
              # clean up the temporary file
              rm_file_or_dir(input_rootdir, ignore_errors=True)
  
          if cache:
              # official end destination
              col_rootdir = os.path.join(self.rootdir, self.create_group_base_name(groupby_cols))
              col_factor_rootdir = col_rootdir + '.factor'
              col_values_rootdir = col_rootdir + '.values'
              lock_file = col_rootdir + '.lock'
  
              # only works for linux
              if not os.path.exists(lock_file):
                  uid = str(uuid.uuid4())
                  try:
                      with open(lock_file, 'a+') as fn:
                          fn.write(uid + '\n')
                      with open(lock_file, 'r') as fn:
                          temp = fn.read().splitlines()
                      if temp[0] == uid:
                          lock = True
                      else:
                          lock = False
                      del temp
                  except:
                      lock = False
              else:
                  lock = False
  
              if lock:
                  rm_file_or_dir(col_factor_rootdir, ignore_errors=False)
                  shutil.move(col_factor_rootdir_tmp, col_factor_rootdir)
                  carray_factor = bcolz.carray(rootdir=col_factor_rootdir, mode='r')
  
                  rm_file_or_dir(col_values_rootdir, ignore_errors=False)
                  shutil.move(col_values_rootdir_tmp, col_values_rootdir)
                  carray_values = bcolz.carray(rootdir=col_values_rootdir, mode='r')
              else:
                  # another process has a lock, we will work with our current files and clean up later
                  self._dir_clean_list.append(col_factor_rootdir)
                  self._dir_clean_list.append(col_values_rootdir)
  
          return carray_factor, carray_values