Repository: dask/dask

Issue:
dask.dataframe.map_partitions docs out of date compared to dask.dataframe.DataFrame.map_partitions
When I look up the documentation for `map_partitions`, I use the search box on the docs page. The top result is usually `dask.dataframe.map_partitions` so that is what I click on and that is the documentation I use as I assume that it is the same or similar to the docs for the method. Recently I wanted to see if map_partitions allows for a function argument like block_info. There is no mention of this on the docs page that I normally go to. I just went to `dask.dataframe.DataFrame.map_partitions` for the first time and I was really surprised by all of the extra information, including mention of a `partition_info` arg.

It seems like the module level function's docs are out of date compared to the `DataFrame` method's. It would be great if the docs were updated considering that the module level function's appear first in in-site searches.

* [module func docs](https://docs.dask.org/en/latest/generated/dask.dataframe.map_partitions.html)
* [method docs](https://docs.dask.org/en/latest/generated/dask.dataframe.DataFrame.map_partitions.html)


Discussion:
@faulaire Yep!
> @faulaire Yep!

Sorry, I removed my reply because I saw that you were talking about an issue on map_partitions and I updated map_overlap documentation in #9145.

So, the issue you are talking about is not resolved. 

Whoops. You are correct. Thanks
Thanks for bring this up! It seems like there is an opportunity to consolidate a lot of docs :) 

I am trying to think what the general solution should be. I looked to numpy to see how they handle this and they basically only have module docs. The method docs immediately link out the the module.

 - [module func docs](https://numpy.org/doc/stable/reference/generated/numpy.mean.html)
 - [method docs](https://numpy.org/doc/stable/reference/generated/numpy.ndarray.mean.html)

So that is one option, remove all the method docs and absorb them into the module docs. 

There is another option which is to programmatically create the method docs _from_ the module docs. We do this kind of thing already for dask methods that are based on other libraries (like numpy or pandas) we use `derived_from` to copy the docs from one place to the other. That seems mildly preferable to me since it would rely on a single source of truth, but have the information wherever the user looks for it rather than making them follow links. 

What do you think?
Yeah the numpy style is what I'm used to. I just checked pandas and they do the latter, however. I guess it comes down to what you all, as the maintainers, find easiest in the long run.

Resolving patch:
diff --git a/dask/array/core.py b/dask/array/core.py
--- a/dask/array/core.py
+++ b/dask/array/core.py
@@ -587,6 +587,7 @@ def map_blocks(
 
     See Also
     --------
+    dask.array.map_overlap : Generalized operation with overlap between neighbors.
     dask.array.blockwise : Generalized operation with control over block alignment.
 
     Examples
@@ -1788,7 +1789,7 @@ def to_hdf5(self, filename, datapath, **kwargs):
 
         See Also
         --------
-        da.store
+        dask.array.store
         h5py.File.create_dataset
         """
         return to_hdf5(filename, datapath, self, **kwargs)
@@ -2096,8 +2097,15 @@ def partitions(self):
         """
         return self.blocks
 
-    @derived_from(np.ndarray)
     def dot(self, other):
+        """Dot product of self and other.
+
+        Refer to :func:`dask.array.tensordot` for full documentation.
+
+        See Also
+        --------
+        dask.array.dot : equivalent function
+        """
         from dask.array.routines import tensordot
 
         return tensordot(self, other, axes=((self.ndim - 1,), (other.ndim - 2,)))
@@ -2110,8 +2118,15 @@ def A(self):
     def T(self):
         return self.transpose()
 
-    @derived_from(np.ndarray)
     def transpose(self, *axes):
+        """Reverse or permute the axes of an array. Return the modified array.
+
+        Refer to :func:`dask.array.transpose` for full documentation.
+
+        See Also
+        --------
+        dask.array.transpose : equivalent function
+        """
         from dask.array.routines import transpose
 
         if not axes:
@@ -2124,27 +2139,42 @@ def transpose(self, *axes):
         else:
             return transpose(self, axes=axes)
 
-    @derived_from(np.ndarray)
     def ravel(self):
+        """Return a flattened array.
+
+        Refer to :func:`dask.array.ravel` for full documentation.
+
+        See Also
+        --------
+        dask.array.ravel : equivalent function
+        """
         from dask.array.routines import ravel
 
         return ravel(self)
 
     flatten = ravel
 
-    @derived_from(np.ndarray)
     def choose(self, choices):
+        """Use an index array to construct a new array from a set of choices.
+
+        Refer to :func:`dask.array.choose` for full documentation.
+
+        See Also
+        --------
+        dask.array.choose : equivalent function
+        """
         from dask.array.routines import choose
 
         return choose(self, choices)
 
-    @derived_from(np.ndarray)
     def reshape(self, *shape, merge_chunks=True, limit=None):
-        """
-        .. note::
+        """Reshape array to new shape
+
+        Refer to :func:`dask.array.reshape` for full documentation.
 
-           See :meth:`dask.array.reshape` for an explanation of
-           the ``merge_chunks`` and `limit` keywords.
+        See Also
+        --------
+        dask.array.reshape : equivalent function
         """
         from dask.array.reshape import reshape
 
@@ -2155,8 +2185,11 @@ def reshape(self, *shape, merge_chunks=True, limit=None):
     def topk(self, k, axis=-1, split_every=None):
         """The top k elements of an array.
 
-        See :func:`dask.array.topk` for docstring.
+        Refer to :func:`dask.array.topk` for full documentation.
 
+        See Also
+        --------
+        dask.array.topk : equivalent function
         """
         from dask.array.reductions import topk
 
@@ -2165,8 +2198,11 @@ def topk(self, k, axis=-1, split_every=None):
     def argtopk(self, k, axis=-1, split_every=None):
         """The indices of the top k elements of an array.
 
-        See :func:`dask.array.argtopk` for docstring.
+        Refer to :func:`dask.array.argtopk` for full documentation.
 
+        See Also
+        --------
+        dask.array.argtopk : equivalent function
         """
         from dask.array.reductions import argtopk
 
@@ -2376,48 +2412,98 @@ def __rdivmod__(self, other):
 
         return divmod(other, self)
 
-    @derived_from(np.ndarray)
     def any(self, axis=None, keepdims=False, split_every=None, out=None):
+        """Returns True if any of the elements evaluate to True.
+
+        Refer to :func:`dask.array.any` for full documentation.
+
+        See Also
+        --------
+        dask.array.any : equivalent function
+        """
         from dask.array.reductions import any
 
         return any(self, axis=axis, keepdims=keepdims, split_every=split_every, out=out)
 
-    @derived_from(np.ndarray)
     def all(self, axis=None, keepdims=False, split_every=None, out=None):
+        """Returns True if all elements evaluate to True.
+
+        Refer to :func:`dask.array.all` for full documentation.
+
+        See Also
+        --------
+        dask.array.all : equivalent function
+        """
         from dask.array.reductions import all
 
         return all(self, axis=axis, keepdims=keepdims, split_every=split_every, out=out)
 
-    @derived_from(np.ndarray)
     def min(self, axis=None, keepdims=False, split_every=None, out=None):
+        """Return the minimum along a given axis.
+
+        Refer to :func:`dask.array.min` for full documentation.
+
+        See Also
+        --------
+        dask.array.min : equivalent function
+        """
         from dask.array.reductions import min
 
         return min(self, axis=axis, keepdims=keepdims, split_every=split_every, out=out)
 
-    @derived_from(np.ndarray)
     def max(self, axis=None, keepdims=False, split_every=None, out=None):
+        """Return the maximum along a given axis.
+
+        Refer to :func:`dask.array.max` for full documentation.
+
+        See Also
+        --------
+        dask.array.max : equivalent function
+        """
         from dask.array.reductions import max
 
         return max(self, axis=axis, keepdims=keepdims, split_every=split_every, out=out)
 
-    @derived_from(np.ndarray)
     def argmin(self, axis=None, *, keepdims=False, split_every=None, out=None):
+        """Return indices of the minimum values along the given axis.
+
+        Refer to :func:`dask.array.argmin` for full documentation.
+
+        See Also
+        --------
+        dask.array.argmin : equivalent function
+        """
         from dask.array.reductions import argmin
 
         return argmin(
             self, axis=axis, keepdims=keepdims, split_every=split_every, out=out
         )
 
-    @derived_from(np.ndarray)
     def argmax(self, axis=None, *, keepdims=False, split_every=None, out=None):
+        """Return indices of the maximum values along the given axis.
+
+        Refer to :func:`dask.array.argmax` for full documentation.
+
+        See Also
+        --------
+        dask.array.argmax : equivalent function
+        """
         from dask.array.reductions import argmax
 
         return argmax(
             self, axis=axis, keepdims=keepdims, split_every=split_every, out=out
         )
 
-    @derived_from(np.ndarray)
     def sum(self, axis=None, dtype=None, keepdims=False, split_every=None, out=None):
+        """
+        Return the sum of the array elements over the given axis.
+
+        Refer to :func:`dask.array.sum` for full documentation.
+
+        See Also
+        --------
+        dask.array.sum : equivalent function
+        """
         from dask.array.reductions import sum
 
         return sum(
@@ -2429,14 +2515,28 @@ def sum(self, axis=None, dtype=None, keepdims=False, split_every=None, out=None)
             out=out,
         )
 
-    @derived_from(np.ndarray)
     def trace(self, offset=0, axis1=0, axis2=1, dtype=None):
+        """Return the sum along diagonals of the array.
+
+        Refer to :func:`dask.array.trace` for full documentation.
+
+        See Also
+        --------
+        dask.array.trace : equivalent function
+        """
         from dask.array.reductions import trace
 
         return trace(self, offset=offset, axis1=axis1, axis2=axis2, dtype=dtype)
 
-    @derived_from(np.ndarray)
     def prod(self, axis=None, dtype=None, keepdims=False, split_every=None, out=None):
+        """Return the product of the array elements over the given axis
+
+        Refer to :func:`dask.array.prod` for full documentation.
+
+        See Also
+        --------
+        dask.array.prod : equivalent function
+        """
         from dask.array.reductions import prod
 
         return prod(
@@ -2448,8 +2548,15 @@ def prod(self, axis=None, dtype=None, keepdims=False, split_every=None, out=None
             out=out,
         )
 
-    @derived_from(np.ndarray)
     def mean(self, axis=None, dtype=None, keepdims=False, split_every=None, out=None):
+        """Returns the average of the array elements along given axis.
+
+        Refer to :func:`dask.array.mean` for full documentation.
+
+        See Also
+        --------
+        dask.array.mean : equivalent function
+        """
         from dask.array.reductions import mean
 
         return mean(
@@ -2461,10 +2568,17 @@ def mean(self, axis=None, dtype=None, keepdims=False, split_every=None, out=None
             out=out,
         )
 
-    @derived_from(np.ndarray)
     def std(
         self, axis=None, dtype=None, keepdims=False, ddof=0, split_every=None, out=None
     ):
+        """Returns the standard deviation of the array elements along given axis.
+
+        Refer to :func:`dask.array.std` for full documentation.
+
+        See Also
+        --------
+        dask.array.std : equivalent function
+        """
         from dask.array.reductions import std
 
         return std(
@@ -2477,10 +2591,17 @@ def std(
             out=out,
         )
 
-    @derived_from(np.ndarray)
     def var(
         self, axis=None, dtype=None, keepdims=False, ddof=0, split_every=None, out=None
     ):
+        """Returns the variance of the array elements, along given axis.
+
+        Refer to :func:`dask.array.var` for full documentation.
+
+        See Also
+        --------
+        dask.array.var : equivalent function
+        """
         from dask.array.reductions import var
 
         return var(
@@ -2505,38 +2626,12 @@ def moment(
     ):
         """Calculate the nth centralized moment.
 
-        Parameters
-        ----------
-        order : int
-            Order of the moment that is returned, must be >= 2.
-        axis : int, optional
-            Axis along which the central moment is computed. The default is to
-            compute the moment of the flattened array.
-        dtype : data-type, optional
-            Type to use in computing the moment. For arrays of integer type the
-            default is float64; for arrays of float types it is the same as the
-            array type.
-        keepdims : bool, optional
-            If this is set to True, the axes which are reduced are left in the
-            result as dimensions with size one. With this option, the result
-            will broadcast correctly against the original array.
-        ddof : int, optional
-            "Delta Degrees of Freedom": the divisor used in the calculation is
-            N - ddof, where N represents the number of elements. By default
-            ddof is zero.
-
-        Returns
-        -------
-        moment : ndarray
-
-        References
-        ----------
-        .. [1] Pebay, Philippe (2008), "Formulas for Robust, One-Pass Parallel
-           Computation of Covariances and Arbitrary-Order Statistical Moments",
-           Technical Report SAND2008-6212, Sandia National Laboratories.
+        Refer to :func:`dask.array.moment` for the full documentation.
 
+        See Also
+        --------
+        dask.array.moment : equivalent function
         """
-
         from dask.array.reductions import moment
 
         return moment(
@@ -2557,85 +2652,11 @@ def map_blocks(self, func, *args, **kwargs):
     def map_overlap(self, func, depth, boundary=None, trim=True, **kwargs):
         """Map a function over blocks of the array with some overlap
 
-        We share neighboring zones between blocks of the array, then map a
-        function, then trim away the neighboring strips.
-
-        Note that this function will attempt to automatically determine the output
-        array type before computing it, please refer to the ``meta`` keyword argument
-        in :func:`map_blocks <dask.array.core.map_blocks>` if you expect that the function will not succeed when
-        operating on 0-d arrays.
+        Refer to :func:`dask.array.map_overlap` for full documentation.
 
-        Parameters
-        ----------
-        func: function
-            The function to apply to each extended block
-        depth: int, tuple, or dict
-            The number of elements that each block should share with its neighbors
-            If a tuple or dict then this can be different per axis
-        boundary: str, tuple, dict
-            How to handle the boundaries.
-            Values include 'reflect', 'periodic', 'nearest', 'none',
-            or any constant value like 0 or np.nan
-        trim: bool
-            Whether or not to trim ``depth`` elements from each block after
-            calling the map function.
-            Set this to False if your mapping function already does this for you
-        **kwargs:
-            Other keyword arguments valid in :func:`map_blocks <dask.array.core.map_blocks>`.
-
-        Examples
+        See Also
         --------
-        >>> import dask.array as da
-        >>> x = np.array([1, 1, 2, 3, 3, 3, 2, 1, 1])
-        >>> x = da.from_array(x, chunks=5)
-        >>> def derivative(x):
-        ...     return x - np.roll(x, 1)
-
-        >>> y = x.map_overlap(derivative, depth=1, boundary=0)
-        >>> y.compute()
-        array([ 1,  0,  1,  1,  0,  0, -1, -1,  0])
-
-        >>> import dask.array as da
-        >>> x = np.arange(16).reshape((4, 4))
-        >>> d = da.from_array(x, chunks=(2, 2))
-        >>> y = d.map_overlap(lambda x: x + x.size, depth=1, boundary='reflect')
-        >>> y.compute()
-        array([[16, 17, 18, 19],
-               [20, 21, 22, 23],
-               [24, 25, 26, 27],
-               [28, 29, 30, 31]])
-
-        >>> func = lambda x: x + x.size
-        >>> depth = {0: 1, 1: 1}
-        >>> boundary = {0: 'reflect', 1: 'none'}
-        >>> d.map_overlap(func, depth, boundary).compute()  # doctest: +NORMALIZE_WHITESPACE
-        array([[12,  13,  14,  15],
-               [16,  17,  18,  19],
-               [20,  21,  22,  23],
-               [24,  25,  26,  27]])
-
-        >>> x = np.arange(16).reshape((4, 4))
-        >>> d = da.from_array(x, chunks=(2, 2))
-        >>> y = d.map_overlap(lambda x: x + x[2], depth=1, boundary='reflect', meta=np.array(()))
-        >>> y
-        dask.array<_trim, shape=(4, 4), dtype=float64, chunksize=(2, 2), chunktype=numpy.ndarray>
-        >>> y.compute()
-        array([[ 4,  6,  8, 10],
-               [ 8, 10, 12, 14],
-               [20, 22, 24, 26],
-               [24, 26, 28, 30]])
-
-        >>> import cupy  # doctest: +SKIP
-        >>> x = cupy.arange(16).reshape((4, 4))  # doctest: +SKIP
-        >>> d = da.from_array(x, chunks=(2, 2))  # doctest: +SKIP
-        >>> y = d.map_overlap(lambda x: x + x[2], depth=1, boundary='reflect', meta=cupy.array(()))  # doctest: +SKIP
-        >>> y  # doctest: +SKIP
-        dask.array<_trim, shape=(4, 4), dtype=float64, chunksize=(2, 2), chunktype=cupy.ndarray>
-        >>> y.compute()  # doctest: +SKIP
-        array([[ 4,  6,  8, 10],
-               [ 8, 10, 12, 14],
-               [20, 22, 24, 26],
-               [24, 26, 28, 30]])
+        dask.array.map_overlap : equivalent function
         """
         from dask.array.overlap import map_overlap
 
@@ -2643,42 +2664,41 @@ def map_overlap(self, func, depth, boundary=None, trim=True, **kwargs):
             func, self, depth=depth, boundary=boundary, trim=trim, **kwargs
         )
 
-    @derived_from(np.ndarray)
     def cumsum(self, axis, dtype=None, out=None, *, method="sequential"):
-        """Dask added an additional keyword-only argument ``method``.
+        """Return the cumulative sum of the elements along the given axis.
 
-        method : {'sequential', 'blelloch'}, optional
-            Choose which method to use to perform the cumsum.  Default is 'sequential'.
+        Refer to :func:`dask.array.cumsum` for full documentation.
 
-            * 'sequential' performs the cumsum of each prior block before the current block.
-            * 'blelloch' is a work-efficient parallel cumsum.  It exposes parallelism by
-              first taking the sum of each block and combines the sums via a binary tree.
-              This method may be faster or more memory efficient depending on workload,
-              scheduler, and hardware.  More benchmarking is necessary.
+        See Also
+        --------
+        dask.array.cumsum : equivalent function
         """
         from dask.array.reductions import cumsum
 
         return cumsum(self, axis, dtype, out=out, method=method)
 
-    @derived_from(np.ndarray)
     def cumprod(self, axis, dtype=None, out=None, *, method="sequential"):
-        """Dask added an additional keyword-only argument ``method``.
+        """Return the cumulative product of the elements along the given axis.
 
-        method : {'sequential', 'blelloch'}, optional
-            Choose which method to use to perform the cumprod.  Default is 'sequential'.
+        Refer to :func:`dask.array.cumprod` for full documentation.
 
-            * 'sequential' performs the cumprod of each prior block before the current block.
-            * 'blelloch' is a work-efficient parallel cumprod.  It exposes parallelism by first
-              taking the product of each block and combines the products via a binary tree.
-              This method may be faster or more memory efficient depending on workload,
-              scheduler, and hardware.  More benchmarking is necessary.
+        See Also
+        --------
+        dask.array.cumprod : equivalent function
         """
         from dask.array.reductions import cumprod
 
         return cumprod(self, axis, dtype, out=out, method=method)
 
-    @derived_from(np.ndarray)
     def squeeze(self, axis=None):
+        """Remove axes of length one from array.
+
+        Refer to :func:`dask.array.squeeze` for full documentation.
+
+        See Also
+        --------
+        dask.array.squeeze : equivalent function
+        """
         from dask.array.routines import squeeze
 
         return squeeze(self, axis)
@@ -2686,7 +2706,14 @@ def squeeze(self, axis=None):
     def rechunk(
         self, chunks="auto", threshold=None, block_size_limit=None, balance=False
     ):
-        """See da.rechunk for docstring"""
+        """Convert blocks in dask array x for new chunks.
+
+        Refer to :func:`dask.array.rechunk` for full documentation.
+
+        See Also
+        --------
+        dask.array.rechunk : equivalent function
+        """
         from dask.array.rechunk import rechunk  # avoid circular import
 
         return rechunk(self, chunks, threshold, block_size_limit, balance)
@@ -2704,12 +2731,28 @@ def imag(self):
         return imag(self)
 
     def conj(self):
+        """Complex-conjugate all elements.
+
+        Refer to :func:`dask.array.conj` for full documentation.
+
+        See Also
+        --------
+        dask.array.conj : equivalent function
+        """
         from dask.array.ufunc import conj
 
         return conj(self)
 
-    @derived_from(np.ndarray)
     def clip(self, min=None, max=None):
+        """Return an array whose values are limited to ``[min, max]``.
+        One of max or min must be given.
+
+        Refer to :func:`dask.array.clip` for full documentation.
+
+        See Also
+        --------
+        dask.array.clip : equivalent function
+        """
         from dask.array.ufunc import clip
 
         return clip(self, min, max)
@@ -2757,14 +2800,28 @@ def view(self, dtype=None, order="C"):
             chunk.view, dtype, order=order, dtype=dtype, chunks=chunks
         )
 
-    @derived_from(np.ndarray)
     def swapaxes(self, axis1, axis2):
+        """Return a view of the array with ``axis1`` and ``axis2`` interchanged.
+
+        Refer to :func:`dask.array.swapaxes` for full documentation.
+
+        See Also
+        --------
+        dask.array.swapaxes : equivalent function
+        """
         from dask.array.routines import swapaxes
 
         return swapaxes(self, axis1, axis2)
 
-    @derived_from(np.ndarray)
     def round(self, decimals=0):
+        """Return array with each element rounded to the given number of decimals.
+
+        Refer to :func:`dask.array.round` for full documentation.
+
+        See Also
+        --------
+        dask.array.round : equivalent function
+        """
         from dask.array.routines import round
 
         return round(self, decimals=decimals)
@@ -2806,14 +2863,28 @@ def to_delayed(self, optimize_graph=True):
         L = ndeepmap(self.ndim, lambda k: Delayed(k, graph, layer=layer), keys)
         return np.array(L, dtype=object)
 
-    @derived_from(np.ndarray)
     def repeat(self, repeats, axis=None):
+        """Repeat elements of an array.
+
+        Refer to :func:`dask.array.repeat` for full documentation.
+
+        See Also
+        --------
+        dask.array.repeat : equivalent function
+        """
         from dask.array.creation import repeat
 
         return repeat(self, repeats, axis=axis)
 
-    @derived_from(np.ndarray)
     def nonzero(self):
+        """Return the indices of the elements that are non-zero.
+
+        Refer to :func:`dask.array.nonzero` for full documentation.
+
+        See Also
+        --------
+        dask.array.nonzero : equivalent function
+        """
         from dask.array.routines import nonzero
 
         return nonzero(self)
@@ -2823,16 +2894,24 @@ def to_zarr(self, *args, **kwargs):
 
         See https://zarr.readthedocs.io for details about the format.
 
-        See function :func:`dask.array.to_zarr` for parameters.
+        Refer to :func:`dask.array.to_zarr` for full documentation.
+
+        See also
+        --------
+        dask.array.to_zarr : equivalent function
         """
         return to_zarr(self, *args, **kwargs)
 
     def to_tiledb(self, uri, *args, **kwargs):
         """Save array to the TileDB storage manager
 
+        See https://docs.tiledb.io for details about the format and engine.
+
         See function :func:`dask.array.to_tiledb` for argument documentation.
 
-        See https://docs.tiledb.io for details about the format and engine.
+        See also
+        --------
+        dask.array.to_tiledb : equivalent function
         """
         from dask.array.tiledb_io import to_tiledb
 
@@ -5558,14 +5637,16 @@ def to_npy_stack(dirname, x, axis=0):
 def from_npy_stack(dirname, mmap_mode="r"):
     """Load dask array from stack of npy files
 
-    See :func:`dask.array.to_npy_stack` for docstring.
-
     Parameters
     ----------
     dirname: string
         Directory of .npy files
     mmap_mode: (None or 'r')
         Read data in memory map mode
+
+    See Also
+    --------
+    to_npy_stack
     """
     with open(os.path.join(dirname, "info"), "rb") as f:
         info = pickle.load(f)
diff --git a/dask/array/reductions.py b/dask/array/reductions.py
--- a/dask/array/reductions.py
+++ b/dask/array/reductions.py
@@ -859,6 +859,41 @@ def moment_agg(
 def moment(
     a, order, axis=None, dtype=None, keepdims=False, ddof=0, split_every=None, out=None
 ):
+    """Calculate the nth centralized moment.
+
+    Parameters
+    ----------
+    a : Array
+        Data over which to compute moment
+    order : int
+        Order of the moment that is returned, must be >= 2.
+    axis : int, optional
+        Axis along which the central moment is computed. The default is to
+        compute the moment of the flattened array.
+    dtype : data-type, optional
+        Type to use in computing the moment. For arrays of integer type the
+        default is float64; for arrays of float types it is the same as the
+        array type.
+    keepdims : bool, optional
+        If this is set to True, the axes which are reduced are left in the
+        result as dimensions with size one. With this option, the result
+        will broadcast correctly against the original array.
+    ddof : int, optional
+        "Delta Degrees of Freedom": the divisor used in the calculation is
+        N - ddof, where N represents the number of elements. By default
+        ddof is zero.
+
+    Returns
+    -------
+    moment : Array
+
+    References
+    ----------
+    .. [1] Pebay, Philippe (2008), "Formulas for Robust, One-Pass Parallel
+        Computation of Covariances and Arbitrary-Order Statistical Moments",
+        Technical Report SAND2008-6212, Sandia National Laboratories.
+
+    """
     if not isinstance(order, Integral) or order < 0:
         raise ValueError("Order must be an integer >= 0")
 


Test patch: