docs: def reduce(self, func, dim=None, keep_attrs=None, numeric_only=False,
                 allow_lazy=False, **kwargs):
          """Reduce this dataset by applying `func` along some dimension(s).
  
          Parameters
          ----------
          func : function
              Function which can be called in the form
              `f(x, axis=axis, **kwargs)` to return the result of reducing an
              np.ndarray over an integer valued axis.
          dim : str or sequence of str, optional
              Dimension(s) over which to apply `func`.  By default `func` is
              applied over all dimensions.
          keep_attrs : bool, optional
              If True, the dataset's attributes (`attrs`) will be copied from
              the original object to the new one.  If False (default), the new
              object will be returned without attributes.
          numeric_only : bool, optional
              If True, only apply ``func`` to variables with a numeric dtype.
          **kwargs : dict
              Additional keyword arguments passed on to ``func``.
  
          Returns
          -------
          reduced : Dataset
              Dataset with this object's DataArrays replaced with new DataArrays
              of summarized data and the indicated dimension(s) removed.
          """
          if dim is ALL_DIMS:
              dim = None
          if isinstance(dim, str):
              dims = set([dim])
          elif dim is None:
              dims = set(self.dims)
          else:
              dims = set(dim)
  
          missing_dimensions = [d for d in dims if d not in self.dims]
          if missing_dimensions:
              raise ValueError('Dataset does not contain the dimensions: %s'
                               % missing_dimensions)
  
          if keep_attrs is None:
              keep_attrs = _get_keep_attrs(default=False)
  
          variables = OrderedDict()
          for name, var in self._variables.items():
              reduce_dims = [d for d in var.dims if d in dims]
              if name in self.coords:
                  if not reduce_dims:
                      variables[name] = var
              else:
                  if (not numeric_only or
                          np.issubdtype(var.dtype, np.number) or
                          (var.dtype == np.bool_)):
                      if len(reduce_dims) == 1:
                          # unpack dimensions for the benefit of functions
                          # like np.argmin which can't handle tuple arguments
                          reduce_dims, = reduce_dims
                      elif len(reduce_dims) == var.ndim:
                          # prefer to aggregate over axis=None rather than
                          # axis=(0, 1) if they will be equivalent, because
                          # the former is often more efficient
                          reduce_dims = None
                      variables[name] = var.reduce(func, dim=reduce_dims,
                                                   keep_attrs=keep_attrs,
                                                   allow_lazy=allow_lazy,
                                                   **kwargs)
  
          coord_names = set(k for k in self.coords if k in variables)
          attrs = self.attrs if keep_attrs else None
          return self._replace_vars_and_dims(variables, coord_names, attrs=attrs)