Repository: numpy/numpy
Issue category: Feature Request

Issue:
DOC: Examples in docstrings – tracking issue
"Examples, more examples, and more detailed examples" is the recurrent theme in the feedback about the NumPy documentation we received via the 2020 and 2021 NumPy user surveys. 

If you come across a docstring where a function is missing an example or more/better examples are needed, please add a comment below.

**Re: the “sprintable” label** This could be a good activity for a sprint with new contributors as most of them are NumPy users. However, one doesn’t have to be a sprint participant to contribute to this initiative.




Hints:
how can I help in this issue ?
Take a look at the functions you use from NumPy, and see if the docstrings have examples similar to your non-trivial use cases. If not, comment below asking if it seems an example would help newer users figure out how to replicate what you do.
This could be a good activity for a sprint with new contributors as most of them are NumPy users. I’ll add the “sprint” label to the issue. However, one doesn’t have to be a sprint participant to contribute to this initiative.
Hi everyone! 

One thing that could also be tracked is whether the existing examples in docstrings are following the standards listed in the documentation. I've found an example in `fromnumeric.py` (lines 171-189) that I'm not entirely sure that are in accordance to the documentation.

I'm willing to help on that.
Hi, Just wanted to confirm. If the general DOCS (examples for various functions) are in the scope of this Issue or we are currently tracking only the DOC Strings. 
I do see a lot of additions that can be done to the `numpy.random.generated` page
[Link under discussion](https://numpy.org/doc/stable/reference/random/generated/numpy.random.Generator.integers.html)
I was talking to @InessaPawson about that. I do believe that this issue could be, in fact, split into several different ones. Even the docstrings, this could be split in tracking down the ones that are there, the ones that are not, the ones that follow the standards, et cetera.
We can use some examples in polynomial.py. What do you think about the following two (one for polymulx, the other for polyval2d):

```python
import numpy as np
from numpy.polynomial import polynomial as P

c=(-2, 0, 1)
P.polymulx(c)
#array([-0., -2.,  0.,  1.])


from numpy.polynomial.polynomial import polyval2d
a=polyval2d(2, -3j,  [(-1j,1.5,2), (1,0.2j,0)])  #This is -1jx⁰y⁰ + 1.5x⁰y¹ + 2x⁰y² + 1x¹y⁰ + 0.2jx¹y¹ + 0x¹y², evaluated at x = 2 and y=-3j
#(-14.799999999999997-5.5j)
```
> Just wanted to confirm. If the general DOCS (examples for various functions) are in the scope of this Issue or we are currently tracking only the DOC Strings.

@bhavukkalra This issue is only for examples in docstrings. Please file a separate issue for examples in other parts of the NumPy documentation.
@dbrs01 this looks good - Would you like to submit a PR? 
Thank you Melisssa. I appreciate your feedback.  I will do it (later) and
will continue including more examples. I have not been able to attend
meetings recently because I started a new job this past Monday and am in
the process of doing paperwork, installing my machine, going to the office
(no telework) and trying to get the most from my coworker from whom I
inherit tasks and whose last day of work is on May 30.  I hope to be back
soon. See you!

On Sat, May 14, 2022 at 7:13 AM Melissa Weber Mendonça <
***@***.***> wrote:

> @dbrs01 <https://github.com/dbrs01> this looks good - Would you like to
> submit a PR?
>
> —
> Reply to this email directly, view it on GitHub
> <https://github.com/numpy/numpy/issues/21351#issuecomment-1126714170>, or
> unsubscribe
> <https://github.com/notifications/unsubscribe-auth/ABXBEHY2CZLX6V47USVDDZLVJ6RJJANCNFSM5TTIU3GA>
> .
> You are receiving this because you were mentioned.Message ID:
> ***@***.***>
>


-- 
Dilia B. Rueda S.

I can help with the PRs if you feel this is something that could help. Feel free to post the examples here and I can submit the PRs.
Some time ago I wrote a script to find SciPy functions whose docstrings are missing the "Examples" section; there is a copy of that script in https://github.com/scipy/scipy/issues/7168. (*Edit*: the script for SciPy, [`find_functions_missing_examples.py`](https://github.com/WarrenWeckesser/analyze-scipy-code/blob/main/find_functions_missing_examples.py) is now maintained in my [`analyze-scipy-code`](https://github.com/WarrenWeckesser/analyze-scipy-code) repository on github.)

I just created a gist with a variation of that script that has been modified for NumPy: https://gist.github.com/WarrenWeckesser/c33d0236279cc5d73843f0497e14ed0e.  (There is a lot that could be done with such a script; hack away on your own copy if you feel inspired.)

Here's the output when I run that script with the development version (main branch) of NumPy.  Note that some of these functions have very short docstrings that say something like "See $SOMEOTHERFUNC for details."  This is probably intentional, and these are not good candidates for new contributors or for use in a sprint.   Also, it looks like some of these might be "namespace pollution": names from the main numpy namespace that also ended up in a submodule.  When in doubt, ask the NumPy devs to confirm that a function should get an "Examples" section before you spend time working on it.

```
NumPy version 1.24.0.dev0+427.gf9bed20bf

np (22)
    add_docstring
    add_newdoc
    add_newdoc_ufunc
    alltrue
    copyto
    cumproduct
    deprecate_with_doc
    diag_indices_from
    fastCopyAndTranspose
    get_array_wrap
    get_include
    get_printoptions
    getbufsize
    msort
    product
    recfromcsv
    recfromtxt
    round_
    setbufsize
    sometrue
    tril_indices_from
    triu_indices_from
np.char (40)
    add
    array
    asarray
    center
    encode
    equal
    expandtabs
    find
    greater
    greater_equal
    index
    isalnum
    isalpha
    isdecimal
    isdigit
    islower
    isnumeric
    isspace
    istitle
    isupper
    join
    less
    less_equal
    ljust
    mod
    multiply
    not_equal
    partition
    replace
    rfind
    rindex
    rjust
    rpartition
    rsplit
    split
    splitlines
    startswith
    str_len
    translate
    zfill
np.ctypeslib (4)
    as_array
    as_ctypes
    as_ctypes_type
    load_library
np.ma (26)
    compress_cols
    compress_nd
    compress_rows
    compressed
    convolve
    correlate
    cov
    diag
    ediff1d
    in1d
    isin
    left_shift
    max
    min
    power
    put
    putmask
    reshape
    right_shift
    round
    round_
    setxor1d
    sort
    take
    union1d
    unique
np.random.Generator (2)
    beta
    exponential

Found 94 functions
```
FWIW this check is also now built-in to the numpydoc docstring validator, which can be run during a doc build. For example, when building the docs locally you can add `numpydoc_validation_checks = {"EX01"}` to `conf.py` to automatically report this info during the sphinx-build process.
@WarrenWeckesser Thank you so much for sharing this information! I’ll file a separate issue for each function after consulting with our core developers.
We should rerun the script
The old script was missing some functions, which I think is because of the issues related to _ArrayFunctionDispatcher from last year. For example https://github.com/numpy/numpy/issues/23032 and https://github.com/numpy/numpy/issues/23307.

I added the following lines to the script. EDIT: Found better way, using `inspect.isroutine`.
```
import inspect
```
Then I replaced `funcs` with 
```
    funcs = [item for item in objects
             if inspect.isroutine(item[1])]
```
Here is the new list:
```
np (12)
    amax
    amin
    around
    getbufsize
    matrix_transpose
    setbufsize
    show_config
    show_runtime
    unique_all
    unique_counts
    unique_inverse
    unique_values
np.char (7)
    array
    isalpha
    isspace
    mod
    rfind
    splitlines
    startswith
np.ctypeslib (4)
    as_array
    as_ctypes
    as_ctypes_type
    load_library
np.lib (2)
    add_docstring
    add_newdoc
np.linalg (10)
    cross
    diagonal
    matmul
    matrix_norm
    matrix_transpose
    outer
    svdvals
    trace
    vecdot
    vector_norm
np.ma (6)
    convolve
    correlate
    left_shift
    put
    reshape
    take
np.rec (1)
    find_duplicate

Found 42 functions
```
Prior to the change, there were only 24. I noticed the script was missing `svdvals`, which is why I started working on it.  My hope is to have the POSSEE team fill in all of these (that need it) by next week.

~~Unfortunately, the type `<class 'numpy._ArrayFunctionDispatcher'>` also captures a few classes that don't need examples. I spent a couple hours reading about the issues last year and changes made related to `_ArrayFunctionDispatcher`.  Maybe someone has an idea of a more elegant fix to the script than what I provided above.~~ Found a better way. 

I tried adding  `numpydoc_validation_checks = {"EX01"}` to `conf.py`, but was unable to see where/how this generated the needed report. I'd love advice on that. 
> I tried adding numpydoc_validation_checks = {"EX01"} to conf.py, but was unable to see where/how this generated the needed report. I'd love advice on that.

When you add `numpydoc_validation_checks = {"EX01"}` to conf.py the validation warnings appear in the sphinx build log. To capture the build log in a file, you can do something like:

`make html 2>&1 | tee buildlog.txt`

If you want to filter the log so that only the warnings associated with the validation checks are stored, try:

`make html 2>&1 | tee >(grep -B1 -A1 "EX01" >> buildlog.txt )`
I'll share the output as a file [buildlog.log](https://github.com/numpy/numpy/files/15408328/buildlog.log), rather than copy/paste the output here.  There are 1808 items.
I modified the script above to use `inspect.isroutine` The results are slightly different than capturing `numpy._ArrayFunctionDispatcher` and then using `isinstance`. [Here I the updated scripts](https://github.com/bmwoodruff/numpy-ideas/blob/main/find_numpy_functions_missing_examples.ipynb), along with the output in a Jupyter notebook.  

While working on this, I noticed that there were several functions on this list that had docstrings that were not published on the web version of the docs. [This script](https://github.com/bmwoodruff/numpy-ideas/blob/main/locate-missing-docs.ipynb) uses the `object.inv` file from a doc build and compares each routine against that list. I'll be including a PR in a bit with the missing `ma` links (they don't show on the attached link, because I added them).  There are 5 functions from the new `strings` module that need to be added as well. I can tackle unless someone else was working on that already (I know `strings` is new in 2.0). 


Created [gist of the script](https://gist.github.com/luxedo/c7ad85b8848136671d126cd7baa07990) to run directly into a python shell.
# Missing Docstrings

### np (12)
- [x] amax - Alias of max. Are examples needed?
- [x] amin - Alias of min
- [x] around - Alias of round
- [x] getbufsize
- [x] matrix_transpose
- [x] setbufsize
- [ ] show_config
- [ ] show_runtime
- [x] unique_all
- [x] unique_counts
- [x] unique_inverse
- [x] unique_values
### np.char (7)
- [x] array
- [ ] isalpha
- [ ] isspace
- [ ] mod
- [ ] rfind
- [ ] splitlines
- [ ] startswith
### np.ctypeslib (4)
- [ ] as_array
- [ ] as_ctypes
- [ ] as_ctypes_type
- [ ] load_library
### np.lib (2)
- [ ] add_docstring
- [ ] add_newdoc
### np.linalg (10)
- [x] cross
- [x] diagonal
- [x] matmul
- [x] matrix_norm
- [x] matrix_transpose
- [x] outer
- [x] svdvals
- [x] trace
- [x] vecdot
- [x] vector_norm
### np.ma (6)
- [ ] convolve
- [ ] correlate
- [ ] left_shift
- [ ] put
- [ ] reshape
- [x] take
### np.rec (1)
- [ ] find_duplicate

I sent too many PRs already. I'll wait for review to add more.
@luxedo If you put `[skip actions][skip azp][skip cirrus]` in your [commit message](https://numpy.org/devdocs/dev/development_workflow.html#writing-the-commit-message), then proper GitHub actions will be skipped and your tests should pass.
Thank you! My bad.
I should not use `[skip circle]` right? The doctests run there?
Correct. They have to be in the commit message as well. Putting them in the comments of the PR is not sufficient (learned that myself a few weeks ago). Any time you add more changes in another commit, you have to add these tags to the commit message to make sure the correct CI jobs are run. 
Also please try to combine small example additions together into one PR
I did like to add examples for the numpy.char.array, currently working on it.
Adding example code snippets to np.char.isspace function, currently in the process of adding it
adding example code snippets to np.ma.convolve function currently in the process of adding it


Patch:
diff --git a/numpy/ctypeslib.py b/numpy/ctypeslib.py
index 370cdf224cdc..d11b9dcb43d3 100644
--- a/numpy/ctypeslib.py
+++ b/numpy/ctypeslib.py
@@ -527,6 +527,26 @@ def as_array(obj, shape=None):
 
         The shape parameter must be given if converting from a ctypes POINTER.
         The shape parameter is ignored if converting from a ctypes array
+
+        Examples
+        --------
+        Converting a ctypes integer array:
+
+        >>> import ctypes
+        >>> ctypes_array = (ctypes.c_int * 5)(0, 1, 2, 3, 4)
+        >>> np_array = np.ctypeslib.as_array(ctypes_array)
+        >>> np_array
+        array([0, 1, 2, 3, 4], dtype=int32)
+
+        Converting a ctypes POINTER:
+
+        >>> import ctypes
+        >>> buffer = (ctypes.c_int * 5)(0, 1, 2, 3, 4)
+        >>> pointer = ctypes.cast(buffer, ctypes.POINTER(ctypes.c_int))
+        >>> np_array = np.ctypeslib.as_array(pointer, (5,))
+        >>> np_array
+        array([0, 1, 2, 3, 4], dtype=int32)
+
         """
         if isinstance(obj, ctypes._Pointer):
             # convert pointers to an array of the desired shape
@@ -541,8 +561,31 @@ def as_array(obj, shape=None):
 
 
     def as_ctypes(obj):
-        """Create and return a ctypes object from a numpy array.  Actually
-        anything that exposes the __array_interface__ is accepted."""
+        """
+        Create and return a ctypes object from a numpy array.  Actually
+        anything that exposes the __array_interface__ is accepted.
+
+        Examples
+        --------
+        Create ctypes object from inferred int ``np.array``:
+
+        >>> inferred_int_array = np.array([1, 2, 3])
+        >>> c_int_array = np.ctypeslib.as_ctypes(inferred_int_array)
+        >>> type(c_int_array)
+        <class 'c_long_Array_3'>
+        >>> c_int_array[:]
+        [1, 2, 3]
+
+        Create ctypes object from explicit 8 bit unsigned int ``np.array`` :
+
+        >>> exp_int_array = np.array([1, 2, 3], dtype=np.uint8)
+        >>> c_int_array = np.ctypeslib.as_ctypes(exp_int_array)
+        >>> type(c_int_array)
+        <class 'c_ubyte_Array_3'>
+        >>> c_int_array[:]
+        [1, 2, 3]
+
+        """
         ai = obj.__array_interface__
         if ai["strides"]:
             raise TypeError("strided arrays not supported")


Test patch: