def expand_dims(
        self,
        dim: None | Hashable | Sequence[Hashable] | Mapping[Any, Any] = None,
        axis: None | int | Sequence[int] = None,
        create_index_for_new_dim: bool = True,
        **dim_kwargs: Any,
    ) -> Self:
        """Return a new object with an additional axis (or axes) inserted at
        the corresponding position in the array shape.  The new object is a
        view into the underlying array, not a copy.

        If dim is already a scalar coordinate, it will be promoted to a 1D
        coordinate consisting of a single value.

        The automatic creation of indexes to back new 1D coordinate variables
        controlled by the create_index_for_new_dim kwarg.

        Parameters
        ----------
        dim : hashable, sequence of hashable, mapping, or None
            Dimensions to include on the new variable. If provided as hashable
            or sequence of hashable, then dimensions are inserted with length
            1. If provided as a mapping, then the keys are the new dimensions
            and the values are either integers (giving the length of the new
            dimensions) or array-like (giving the coordinates of the new
            dimensions).
        axis : int, sequence of int, or None, default: None
            Axis position(s) where new axis is to be inserted (position(s) on
            the result array). If a sequence of integers is passed,
            multiple axes are inserted. In this case, dim arguments should be
            same length list. If axis=None is passed, all the axes will be
            inserted to the start of the result array.
        create_index_for_new_dim : bool, default: True
            Whether to create new ``PandasIndex`` objects when the object being expanded contains scalar variables with names in ``dim``.
        **dim_kwargs : int or sequence or ndarray
            The keywords are arbitrary dimensions being inserted and the values
            are either the lengths of the new dims (if int is given), or their
            coordinates. Note, this is an alternative to passing a dict to the
            dim kwarg and will only be used if dim is None.

        Returns
        -------
        expanded : Dataset
            This object, but with additional dimension(s).

        Examples
        --------
        >>> dataset = xr.Dataset({"temperature": ([], 25.0)})
        >>> dataset
        <xarray.Dataset> Size: 8B
        Dimensions:      ()
        Data variables:
            temperature  float64 8B 25.0

        # Expand the dataset with a new dimension called "time"

        >>> dataset.expand_dims(dim="time")
        <xarray.Dataset> Size: 8B
        Dimensions:      (time: 1)
        Dimensions without coordinates: time
        Data variables:
            temperature  (time) float64 8B 25.0

        # 1D data

        >>> temperature_1d = xr.DataArray([25.0, 26.5, 24.8], dims="x")
        >>> dataset_1d = xr.Dataset({"temperature": temperature_1d})
        >>> dataset_1d
        <xarray.Dataset> Size: 24B
        Dimensions:      (x: 3)
        Dimensions without coordinates: x
        Data variables:
            temperature  (x) float64 24B 25.0 26.5 24.8

        # Expand the dataset with a new dimension called "time" using axis argument

        >>> dataset_1d.expand_dims(dim="time", axis=0)
        <xarray.Dataset> Size: 24B
        Dimensions:      (time: 1, x: 3)
        Dimensions without coordinates: time, x
        Data variables:
            temperature  (time, x) float64 24B 25.0 26.5 24.8

        # 2D data

        >>> temperature_2d = xr.DataArray(np.random.rand(3, 4), dims=("y", "x"))
        >>> dataset_2d = xr.Dataset({"temperature": temperature_2d})
        >>> dataset_2d
        <xarray.Dataset> Size: 96B
        Dimensions:      (y: 3, x: 4)
        Dimensions without coordinates: y, x
        Data variables:
            temperature  (y, x) float64 96B 0.5488 0.7152 0.6028 ... 0.7917 0.5289

        # Expand the dataset with a new dimension called "time" using axis argument

        >>> dataset_2d.expand_dims(dim="time", axis=2)
        <xarray.Dataset> Size: 96B
        Dimensions:      (y: 3, x: 4, time: 1)
        Dimensions without coordinates: y, x, time
        Data variables:
            temperature  (y, x, time) float64 96B 0.5488 0.7152 0.6028 ... 0.7917 0.5289

        # Expand a scalar variable along a new dimension of the same name with and without creating a new index

        >>> ds = xr.Dataset(coords={"x": 0})
        >>> ds
        <xarray.Dataset> Size: 8B
        Dimensions:  ()
        Coordinates:
            x        int64 8B 0
        Data variables:
            *empty*

        >>> ds.expand_dims("x")
        <xarray.Dataset> Size: 8B
        Dimensions:  (x: 1)
        Coordinates:
          * x        (x) int64 8B 0
        Data variables:
            *empty*

        >>> ds.expand_dims("x").indexes
        Indexes:
            x        Index([0], dtype='int64', name='x')

        >>> ds.expand_dims("x", create_index_for_new_dim=False).indexes
        Indexes:
            *empty*

        See Also
        --------
        DataArray.expand_dims
        """
        if dim is None:
            pass
        elif isinstance(dim, Mapping):
            # We're later going to modify dim in place; don't tamper with
            # the input
            dim = dict(dim)
        elif isinstance(dim, int):
            raise TypeError(
                "dim should be hashable or sequence of hashables or mapping"
            )
        elif isinstance(dim, str) or not isinstance(dim, Sequence):
            dim = {dim: 1}
        elif isinstance(dim, Sequence):
            if len(dim) != len(set(dim)):
                raise ValueError("dims should not contain duplicate values.")
            dim = dict.fromkeys(dim, 1)

        dim = either_dict_or_kwargs(dim, dim_kwargs, "expand_dims")
        assert isinstance(dim, MutableMapping)

        if axis is None:
            axis = list(range(len(dim)))
        elif not isinstance(axis, Sequence):
            axis = [axis]

        if len(dim) != len(axis):
            raise ValueError("lengths of dim and axis should be identical.")
        for d in dim:
            if d in self.dims:
                raise ValueError(f"Dimension {d} already exists.")
            if d in self._variables and not utils.is_scalar(self._variables[d]):
                raise ValueError(f"{d} already exists as coordinate or variable name.")

        variables: dict[Hashable, Variable] = {}
        indexes: dict[Hashable, Index] = dict(self._indexes)
        coord_names = self._coord_names.copy()
        # If dim is a dict, then ensure that the values are either integers
        # or iterables.
        for k, v in dim.items():
            if hasattr(v, "__iter__"):
                # If the value for the new dimension is an iterable, then
                # save the coordinates to the variables dict, and set the
                # value within the dim dict to the length of the iterable
                # for later use.

                if create_index_for_new_dim:
                    index = PandasIndex(v, k)
                    indexes[k] = index
                    name_and_new_1d_var = index.create_variables()
                else:
                    name_and_new_1d_var = {k: Variable(data=v, dims=k)}
                variables.update(name_and_new_1d_var)
                coord_names.add(k)
                dim[k] = variables[k].size
            elif isinstance(v, int):
                pass  # Do nothing if the dimensions value is just an int
            else:
                raise TypeError(
                    f"The value of new dimension {k} must be an iterable or an int"
                )

        for k, v in self._variables.items():
            if k not in dim:
                if k in coord_names:  # Do not change coordinates
                    variables[k] = v
                else:
                    result_ndim = len(v.dims) + len(axis)
                    for a in axis:
                        if a < -result_ndim or result_ndim - 1 < a:
                            raise IndexError(
                                f"Axis {a} of variable {k} is out of bounds of the "
                                f"expanded dimension size {result_ndim}"
                            )

                    axis_pos = [a if a >= 0 else result_ndim + a for a in axis]
                    if len(axis_pos) != len(set(axis_pos)):
                        raise ValueError("axis should not contain duplicate values")
                    # We need to sort them to make sure `axis` equals to the
                    # axis positions of the result array.
                    zip_axis_dim = sorted(zip(axis_pos, dim.items(), strict=True))

                    all_dims = list(zip(v.dims, v.shape, strict=True))
                    for d, c in zip_axis_dim:
                        all_dims.insert(d, c)
                    variables[k] = v.set_dims(dict(all_dims))
            elif k not in variables:
                if k in coord_names and create_index_for_new_dim:
                    # If dims includes a label of a non-dimension coordinate,
                    # it will be promoted to a 1D coordinate with a single value.
                    index, index_vars = create_default_index_implicit(v.set_dims(k))
                    indexes[k] = index
                    variables.update(index_vars)
                else:
                    if create_index_for_new_dim:
                        warnings.warn(
                            f"No index created for dimension {k} because variable {k} is not a coordinate. "
                            f"To create an index for {k}, please first call `.set_coords('{k}')` on this object.",
                            UserWarning,
                            stacklevel=2,
                        )

                    # create 1D variable without creating a new index
                    new_1d_var = v.set_dims(k)
                    variables.update({k: new_1d_var})

        return self._replace_with_new_dims(
            variables, coord_names=coord_names, indexes=indexes
        )
Return a new object with an additional axis (or axes) inserted at
        the corresponding position in the array shape.  The new object is a
        view into the underlying array, not a copy.

        If dim is already a scalar coordinate, it will be promoted to a 1D
        coordinate consisting of a single value.

        The automatic creation of indexes to back new 1D coordinate variables
        controlled by the create_index_for_new_dim kwarg.

        Parameters
        ----------
        dim : hashable, sequence of hashable, mapping, or None
            Dimensions to include on the new variable. If provided as hashable
            or sequence of hashable, then dimensions are inserted with length
            1. If provided as a mapping, then the keys are the new dimensions
            and the values are either integers (giving the length of the new
            dimensions) or array-like (giving the coordinates of the new
            dimensions).
        axis : int, sequence of int, or None, default: None
            Axis position(s) where new axis is to be inserted (position(s) on
            the result array). If a sequence of integers is passed,
            multiple axes are inserted. In this case, dim arguments should be
            same length list. If axis=None is passed, all the axes will be
            inserted to the start of the result array.
        create_index_for_new_dim : bool, default: True
            Whether to create new ``PandasIndex`` objects when the object being expanded contains scalar variables with names in ``dim``.
        **dim_kwargs : int or sequence or ndarray
            The keywords are arbitrary dimensions being inserted and the values
            are either the lengths of the new dims (if int is given), or their
            coordinates. Note, this is an alternative to passing a dict to the
            dim kwarg and will only be used if dim is None.

        Returns
        -------
        expanded : Dataset
            This object, but with additional dimension(s).

        Examples
        --------
        >>> dataset = xr.Dataset({"temperature": ([], 25.0)})
        >>> dataset
        <xarray.Dataset> Size: 8B
        Dimensions:      ()
        Data variables:
            temperature  float64 8B 25.0

        # Expand the dataset with a new dimension called "time"

        >>> dataset.expand_dims(dim="time")
        <xarray.Dataset> Size: 8B
        Dimensions:      (time: 1)
        Dimensions without coordinates: time
        Data variables:
            temperature  (time) float64 8B 25.0

        # 1D data

        >>> temperature_1d = xr.DataArray([25.0, 26.5, 24.8], dims="x")
        >>> dataset_1d = xr.Dataset({"temperature": temperature_1d})
        >>> dataset_1d
        <xarray.Dataset> Size: 24B
        Dimensions:      (x: 3)
        Dimensions without coordinates: x
        Data variables:
            temperature  (x) float64 24B 25.0 26.5 24.8

        # Expand the dataset with a new dimension called "time" using axis argument

        >>> dataset_1d.expand_dims(dim="time", axis=0)
        <xarray.Dataset> Size: 24B
        Dimensions:      (time: 1, x: 3)
        Dimensions without coordinates: time, x
        Data variables:
            temperature  (time, x) float64 24B 25.0 26.5 24.8

        # 2D data

        >>> temperature_2d = xr.DataArray(np.random.rand(3, 4), dims=("y", "x"))
        >>> dataset_2d = xr.Dataset({"temperature": temperature_2d})
        >>> dataset_2d
        <xarray.Dataset> Size: 96B
        Dimensions:      (y: 3, x: 4)
        Dimensions without coordinates: y, x
        Data variables:
            temperature  (y, x) float64 96B 0.5488 0.7152 0.6028 ... 0.7917 0.5289

        # Expand the dataset with a new dimension called "time" using axis argument

        >>> dataset_2d.expand_dims(dim="time", axis=2)
        <xarray.Dataset> Size: 96B
        Dimensions:      (y: 3, x: 4, time: 1)
        Dimensions without coordinates: y, x, time
        Data variables:
            temperature  (y, x, time) float64 96B 0.5488 0.7152 0.6028 ... 0.7917 0.5289

        # Expand a scalar variable along a new dimension of the same name with and without creating a new index

        >>> ds = xr.Dataset(coords={"x": 0})
        >>> ds
        <xarray.Dataset> Size: 8B
        Dimensions:  ()
        Coordinates:
            x        int64 8B 0
        Data variables:
            *empty*

        >>> ds.expand_dims("x")
        <xarray.Dataset> Size: 8B
        Dimensions:  (x: 1)
        Coordinates:
          * x        (x) int64 8B 0
        Data variables:
            *empty*

        >>> ds.expand_dims("x").indexes
        Indexes:
            x        Index([0], dtype='int64', name='x')

        >>> ds.expand_dims("x", create_index_for_new_dim=False).indexes
        Indexes:
            *empty*

        See Also
        --------
        DataArray.expand_dims
        
xarray/core/dataset.py