code: def _reduce(self, func, axis=0):
          
          if self.mode == 'local':
              axes = sorted(tupleize(axis))
  
              # if the function is a ufunc, it can automatically handle reducing over multiple axes
              if isinstance(func, ufunc):
                  inshape(self.shape, axes)
                  reduced = func.reduce(self, axis=tuple(axes))
              else:
                  reshaped = self._align(axes)
                  reduced = reduce(func, reshaped)
  
              # ensure that the shape of the reduced array is valid
              expected_shape = [self.shape[i] for i in range(len(self.shape)) if i not in axes]
              if reduced.shape != tuple(expected_shape):
                  raise ValueError("reduce did not yield an array with valid dimensions")
  
              return self._constructor(reduced[newaxis, :]).__finalize__(self)
  
          if self.mode == 'spark':
              reduced = self.values.reduce(func, axis, keepdims=True)
              return self._constructor(reduced).__finalize__(self)
docs: Reduce an array along an axis.
  
          Applies an associative/commutative function of two arguments
          cumulatively to all arrays along an axis. Array will be aligned
          so that the desired set of axes are in the keys, which may
          require a transpose/reshape.
  
          Parameters
          ----------
          func : function
              Function of two arrays that returns a single array
  
          axis : tuple or int, optional, default=(0,)
              Axis or multiple axes to reduce along.