class_docstr: Distributional model components
  
  Parameters
  ----------
  design : formulae.DesignMatrices
      The object with all the required design matrices and information about the model terms.
  priors : dict
      A dictionary where keys are term names and values are their priors.
  response_name : str
      The name of the response or target. If ``response_kind`` is ``"data"``, it's the name of
      the response variable. If ``response_kind`` is ``"param"`` it's the name of the parameter.
      An example of the first could be "Reaction" and an example of the latter could be "sigma"
      or "kappa".
  response_kind : str
      Specifies whether the distributional component models the response (``"data"``) or an
      auxiliary parameter (``"param"``). When ``"data"`` this is actually modeling the "parent"
      parameter of the family.
  spec : bambi.Model
      The Bambi model
code: def _construct_u_with_new_groups(
      self, posterior, to_stack_dims, factors_with_new_levels
  ):
      u_list = []
      names_list = []
      factor_idxs = {}
      draw_n = len(posterior.coords["draw"])
      chain_n = len(posterior.coords["chain"])
      rng = np.random.default_rng()
      seq_draw = np.arange(draw_n)
      seq_chain = np.arange(chain_n)
  
      if len(to_stack_dims) == 2:  # univariate response
          is_univariate = True
      elif len(to_stack_dims) == 3:  # multivariate response
          is_univariate = False
  
      for factor in factors_with_new_levels:
          term_names = self.group_specific_groups[factor]
          for name in term_names:
              term = self.group_specific_terms[name]
              aliased_term_name = get_aliased_name(term)
              names_list.append(aliased_term_name)
  
              if term.alias:
                  expr_dim = term.alias + "__expr_dim"
                  factor_dim = term.alias + "__factor_dim"
              else:
                  expr, factor = term.name.split("|")
                  expr_dim = expr + "__expr_dim"
                  factor_dim = factor + "__factor_dim"
  
              # For a given factor, we select the same draws to account for correlations.
              if factor in factor_idxs:
                  factor_sampled_idxs = factor_idxs[factor]
              else:
                  factor_levels = posterior.coords[factor_dim]
                  factor_sampled_idxs = rng.choice(
                      np.arange(len(factor_levels)), size=draw_n
                  )
                  factor_idxs[factor] = factor_sampled_idxs
  
              draws_original = posterior[aliased_term_name].to_numpy()
  
              if is_univariate:
                  # Numeric predictors
                  if draws_original.ndim == 3:
                      draws_new_group = draws_original[
                          :, seq_draw, factor_sampled_idxs
                      ]
                      coords = {
                          "chain": seq_chain,
                          "draw": seq_draw,
                          factor_dim: ["__NEW_FACTOR_GROUP__"],
                      }
                  # Categoric predictors
                  elif draws_original.ndim == 4:
                      draws_new_group = draws_original[
                          :, seq_draw, :, factor_sampled_idxs
                      ]
                      # Don't know why, but the previous indexing swaps axes, we fix it
                      draws_new_group = np.swapaxes(
                          draws_new_group, 0, 1
                      )
                      expr_levels = posterior.coords[
                          expr_dim
                      ].to_numpy()
                      coords = {
                          "chain": seq_chain,
                          "draw": seq_draw,
                          expr_dim: expr_levels,
                          factor_dim: ["__NEW_FACTOR_GROUP__"],
                      }
              else:
                  response_dim = to_stack_dims[-1]
                  if draws_original.ndim == 4:
                      draws_new_group = draws_original[
                          :, seq_draw, :, factor_sampled_idxs
                      ]
                      draws_new_group = np.swapaxes(
                          draws_new_group, 0, 1
                      )
                      coords = {
                          "chain": seq_chain,
                          "draw": seq_draw,
                          response_dim: posterior.coords[
                              response_dim
                          ].to_numpy(),
                          factor_dim: ["__NEW_FACTOR_GROUP__"],
                      }
                  elif draws_original.ndim == 5:
                      draws_new_group = draws_original[
                          :, seq_draw, :, :, factor_sampled_idxs
                      ]
                      draws_new_group = np.swapaxes(
                          draws_new_group, 0, 1
                      )
                      expr_levels = posterior.coords[
                          expr_dim
                      ].to_numpy()
                      coords = {
                          "chain": seq_chain,
                          "draw": seq_draw,
                          response_dim: posterior.coords[
                              response_dim
                          ].to_numpy(),
                          expr_dim: expr_levels,
                          factor_dim: ["__NEW_FACTOR_GROUP__"],
                      }
  
              draws_new_group = xr.DataArray(
                  draws_new_group[..., np.newaxis], coords=coords
              )
  
              u_list.append(
                  xr.concat(
                      [posterior[aliased_term_name], draws_new_group],
                      dim=factor_dim,
                  )
              )
  
      # Get a new xr.Dataset with the draws of the terms that have new groups
      u = xr.Dataset(dict(zip(names_list, u_list)))
  
      # Get a xr.Dataset with the draws of the terms that don't have new groups
      Z_terms = [
          get_aliased_name(term)
          for term in self.group_specific_terms.values()
          if get_aliased_name(term) not in names_list
      ]
      if Z_terms:
          u = xr.merge([u, posterior[Z_terms]])
  
      return u
  
imports: import formulae
  import numpy
  import xarray
  from bambi.defaults import get_default_prior
  from bambi.families import univariate, multivariate
  from bambi.priors import Prior
  from bambi.terms import CommonTerm, GroupSpecificTerm, HSGPTerm, OffsetTerm, ResponseTerm
  from bambi.utils import get_aliased_name, is_hsgp_term
label_desc: Use image node_id 11 for calling the DistributionalComponent obj's underlying member method code with example usage: obj._construct_u_with_new_groups(posterior, to_stack_dims, factors_with_new_levels) and returns: u