DOC: Added MultiIndex Example for Series Min
State: closed

Corollary to #23298
- [X] tests added / passed
- [X] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`


Labels:
name: Docs
name: MultiIndex

Comments:
Hello @vadakattu! Thanks for updating the PR.



Cheers ! There are no PEP8 issues in this Pull Request. :beers: 

##### Comment last updated on December 22, 2018 at 18:21 Hours UTC
# [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/23338?src=pr&el=h1) Report
> Merging [#23338](https://codecov.io/gh/pandas-dev/pandas/pull/23338?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/3e0358d869f8a76b3223e8bb313a92edbaa369db?src=pr&el=desc) will **increase** coverage by `<.01%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/pandas-dev/pandas/pull/23338/graphs/tree.svg?width=650&token=eZ4WkYLtcO&height=150&src=pr)](https://codecov.io/gh/pandas-dev/pandas/pull/23338?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master   #23338      +/-   ##
==========================================
+ Coverage    92.3%    92.3%   +<.01%     
==========================================
  Files         162      162              
  Lines       51875    51879       +4     
==========================================
+ Hits        47883    47888       +5     
+ Misses       3992     3991       -1
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `90.71% <100%> (ø)` | :arrow_up: |
| #single | `42.99% <100%> (-0.01%)` | :arrow_down: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/23338?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/core/generic.py](https://codecov.io/gh/pandas-dev/pandas/pull/23338/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZ2VuZXJpYy5weQ==) | `96.62% <100%> (ø)` | :arrow_up: |
| [pandas/util/testing.py](https://codecov.io/gh/pandas-dev/pandas/pull/23338/diff?src=pr&el=tree#diff-cGFuZGFzL3V0aWwvdGVzdGluZy5weQ==) | `87.84% <0%> (+0.09%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/23338?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/23338?src=pr&el=footer). Last update [3e0358d...8ec816a](https://codecov.io/gh/pandas-dev/pandas/pull/23338?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

cc @datapythonista @WillAyd 
@vadakattu can you template this as @datapythonista suggests?
Of course! ...that was very absent minded of me.

Do you have any suggestions for a better way to do the templating? Otherwise I'll go ahead and switch it to old-style formatting.
You can do the same, but without f-strings. If you need a reference, `upper`, `lower`... in `strings.py` also share docstring.
@vadakattu can you please merge master into your branch and push, and make sure the CI is green, so we can merge this. Thanks!
Validate doc strings seems to have a bug with the example validation which is causing failure for one of the build jobs -- it's not picking up the lines immediately beneath it.  (Applies to all 3 functions)

Full output of validate doc string below:

```
################################################################################
######################## Docstring (pandas.Series.min)  ########################
################################################################################

This method returns the minimum of the values in the object.
            If you want the *index* of the minimum, use ``idxmin``. This is
            the equivalent of the ``numpy.ndarray`` method ``argmin``.

Parameters
----------
axis : {index (0)}
skipna : boolean, default True
    Exclude NA/null values when computing the result.
level : int or level name, default None
    If the axis is a MultiIndex (hierarchical), count along a
    particular level, collapsing into a scalar
numeric_only : boolean, default None
    Include only float, int, boolean columns. If None, will attempt to use
    everything, then use only numeric data. Not implemented for Series.

Returns
-------
min : scalar or Series (if level specified)

Examples
--------
``MultiIndex`` series example of monthly rainfall

>>> index = pd.MultiIndex.from_product(
...     [['London', 'New York'], ['Jun', 'Jul', 'Aug']],
...     names=['city', 'month'])
>>> s = pd.Series([47, 35, 54, 112, 117, 113], index=index)
city      month
London    Jun       47
          Jul       35
          Aug       54
New York  Jun      112
          Jul      117
          Aug      113
dtype: int64

>>> s.min()
35

Minimize using level names, as well as indices.

>>> s.min(level='city')
city
London       35
New York    112
dtype: int64

>>> s.min(level=1)
month
Jun    47
Jul    35
Aug    54
dtype: int64

################################################################################
################################## Validation ##################################
################################################################################

11 Errors found:
        Docstring text (summary) should start in the line immediately after the opening quotes (not in the same line, or leaving a blank line in between)
        Use only one blank line to separate sections or paragraphs
        Summary must start with infinitive verb, not third person (e.g. use "Generate" instead of "Generates")
        Summary should fit in a single line.
        Errors in parameters section
                Parameters {**kwargs} not documented
                Parameter "axis" has no description
                Parameter "skipna" type should use "bool" instead of "boolean"
                Parameter "level" description should finish with "."
                Parameter "numeric_only" type should use "bool" instead of "boolean"
        Examples do not pass tests
1 Warnings found:
        See Also section not found

################################################################################
################################### Doctests ###################################
################################################################################

**********************************************************************
Line 30, in pandas.Series.min
Failed example:
    s = pd.Series([47, 35, 54, 112, 117, 113], index=index)
Expected:
    city      month
    London    Jun       47
              Jul       35
              Aug       54
    New York  Jun      112
              Jul      117
              Aug      113
    dtype: int64
Got nothing
```

I can also looking into correcting the pre-existing issues with this functions parameter documentation if you'd like. Else I can leave that for a separate PR.
The validation seems right.

```
>>> s = pd.Series([47, 35, 54, 112, 117, 113], index=index)
city      month
London    Jun       47
          Jul       35
          Aug       54
New York  Jun      112
          Jul      117
          Aug      113
dtype: int64
```

Is wrong. If you assign the `Series` to `s`, nothing is returned by this. Are you missing a `>>> s` in the next line?
Got what you mean -- I think the slight bug / unexpected behaviour is the wording of the message

Sounds like it should be:
```
Got: ...
Expected: nothing
```
instead of the other way around.
@datapythonista how does this look
@vadakattu do you have time to update the PR based on the previous comment?
Will do.
@vadakattu do you have time to address that last comment?
yes, will do this week.
The idea was to change the variables to the new format too (e.g. `%s` -> `{}`)
Done.
I think this is modifying some the same things as #22554. @vadakattu @Roald87, can you coordinate and avoid duplicate work
Have now restructured `_num_doc`, and incorporated the minimal changes necessary across the stat functions (as desired in #22554) such min, max & sum have fully compliant docstrings.

`./scripts/validate_docstrings.py pandas.Series.min`
```
################################################################################
######################## Docstring (pandas.Series.min)  ########################
################################################################################

Return the minimum of the values for the requested axis.

            If you want the *index* of the minimum, use ``idxmin``. This is
            the equivalent of the ``numpy.ndarray`` method ``argmin``.

Parameters
----------
axis : {index (0)}
    Axis for the function to be applied on.
skipna : bool, default True
    Exclude NA/null values when computing the result.
level : int or level name, default None
    If the axis is a MultiIndex (hierarchical), count along a
    particular level, collapsing into a scalar.
numeric_only : bool, default None
    Include only float, int, boolean columns. If None, will attempt to use
    everything, then use only numeric data. Not implemented for Series.
**kwargs
    Additional keyword arguments to be passed to the function.

Returns
-------
min : scalar or Series (if level specified)

Examples
--------

>>> idx = pd.MultiIndex.from_arrays([
...     ['warm', 'warm', 'cold', 'cold'],
...     ['dog', 'falcon', 'fish', 'spider']],
...     names=['blooded', 'animal'])
>>> s = pd.Series([4, 2, 0, 8], name='legs', index=idx)
>>> s
blooded  animal
warm     dog       4
         falcon    2
cold     fish      0
         spider    8
Name: legs, dtype: int64

>>> s.min()
0

Min using level names, as well as indices.

>>> s.min(level='blooded')
blooded
warm    2
cold    0
Name: legs, dtype: int64

>>> s.min(level=0)
blooded
warm    2
cold    0
Name: legs, dtype: int64

See Also
--------
Series.sum : Return the sum.
Series.min : Return the minimum.
Series.max : Return the maximum.
Series.idxmin : Return the index of the minimum.
Series.idxmax : Return the index of the maximum.
DataFrame.min : Return the sum over the requested axis.
DataFrame.min : Return the minimum over the requested axis.
DataFrame.max : Return the maximum over the requested axis.
DataFrame.idxmin : Return the index of the minimum over the requested axis.
DataFrame.idxmax : Return the index of the maximum over the requested axis.

################################################################################
################################## Validation ##################################
################################################################################

Docstring for "pandas.Series.min" correct. :)
```
`./scripts/validate_docstrings.py pandas.Series.max`
```
################################################################################
######################## Docstring (pandas.Series.max)  ########################
################################################################################

Return the maximum of the values for the requested axis.

            If you want the *index* of the maximum, use ``idxmax``. This is
            the equivalent of the ``numpy.ndarray`` method ``argmax``.

Parameters
----------
axis : {index (0)}
    Axis for the function to be applied on.
skipna : bool, default True
    Exclude NA/null values when computing the result.
level : int or level name, default None
    If the axis is a MultiIndex (hierarchical), count along a
    particular level, collapsing into a scalar.
numeric_only : bool, default None
    Include only float, int, boolean columns. If None, will attempt to use
    everything, then use only numeric data. Not implemented for Series.
**kwargs
    Additional keyword arguments to be passed to the function.

Returns
-------
max : scalar or Series (if level specified)

Examples
--------

>>> idx = pd.MultiIndex.from_arrays([
...     ['warm', 'warm', 'cold', 'cold'],
...     ['dog', 'falcon', 'fish', 'spider']],
...     names=['blooded', 'animal'])
>>> s = pd.Series([4, 2, 0, 8], name='legs', index=idx)
>>> s
blooded  animal
warm     dog       4
         falcon    2
cold     fish      0
         spider    8
Name: legs, dtype: int64

>>> s.max()
8

Max using level names, as well as indices.

>>> s.max(level='blooded')
blooded
warm    4
cold    8
Name: legs, dtype: int64

>>> s.max(level=0)
blooded
warm    4
cold    8
Name: legs, dtype: int64

See Also
--------
Series.sum : Return the sum.
Series.min : Return the minimum.
Series.max : Return the maximum.
Series.idxmin : Return the index of the minimum.
Series.idxmax : Return the index of the maximum.
DataFrame.min : Return the sum over the requested axis.
DataFrame.min : Return the minimum over the requested axis.
DataFrame.max : Return the maximum over the requested axis.
DataFrame.idxmin : Return the index of the minimum over the requested axis.
DataFrame.idxmax : Return the index of the maximum over the requested axis.

################################################################################
################################## Validation ##################################
################################################################################

Docstring for "pandas.Series.max" correct. :)
```
`./scripts/validate_docstrings.py pandas.Series.sum`
```
################################################################################
######################## Docstring (pandas.Series.sum)  ########################
################################################################################

Return the sum of the values for the requested axis.

            This is equivalent to the method ``numpy.sum``.

Parameters
----------
axis : {index (0)}
    Axis for the function to be applied on.
skipna : bool, default True
    Exclude NA/null values when computing the result.
level : int or level name, default None
    If the axis is a MultiIndex (hierarchical), count along a
    particular level, collapsing into a scalar.
numeric_only : bool, default None
    Include only float, int, boolean columns. If None, will attempt to use
    everything, then use only numeric data. Not implemented for Series.
min_count : int, default 0
    The required number of valid values to perform the operation. If fewer than
    ``min_count`` non-NA values are present the result will be NA.

    .. versionadded :: 0.22.0

       Added with the default being 0. This means the sum of an all-NA
       or empty Series is 0, and the product of an all-NA or empty
       Series is 1.
**kwargs
    Additional keyword arguments to be passed to the function.

Returns
-------
sum : scalar or Series (if level specified)

Examples
--------

>>> idx = pd.MultiIndex.from_arrays([
...     ['warm', 'warm', 'cold', 'cold'],
...     ['dog', 'falcon', 'fish', 'spider']],
...     names=['blooded', 'animal'])
>>> s = pd.Series([4, 2, 0, 8], name='legs', index=idx)
>>> s
blooded  animal
warm     dog       4
         falcon    2
cold     fish      0
         spider    8
Name: legs, dtype: int64

>>> s.sum()
14

Sum using level names, as well as indices.

>>> s.sum(level='blooded')
blooded
warm    6
cold    8
Name: legs, dtype: int64

>>> s.sum(level=0)
blooded
warm    6
cold    8
Name: legs, dtype: int64

By default, the sum of an empty or all-NA Series is ``0``.

>>> pd.Series([]).sum()  # min_count=0 is the default
0.0

This can be controlled with the ``min_count`` parameter. For example, if
you'd like the sum of an empty series to be NaN, pass ``min_count=1``.

>>> pd.Series([]).sum(min_count=1)
nan

Thanks to the ``skipna`` parameter, ``min_count`` handles all-NA and
empty series identically.

>>> pd.Series([np.nan]).sum()
0.0

>>> pd.Series([np.nan]).sum(min_count=1)
nan

See Also
--------
Series.sum : Return the sum.
Series.min : Return the minimum.
Series.max : Return the maximum.
Series.idxmin : Return the index of the minimum.
Series.idxmax : Return the index of the maximum.
DataFrame.min : Return the sum over the requested axis.
DataFrame.min : Return the minimum over the requested axis.
DataFrame.max : Return the maximum over the requested axis.
DataFrame.idxmin : Return the index of the minimum over the requested axis.
DataFrame.idxmax : Return the index of the maximum over the requested axis.

################################################################################
################################## Validation ##################################
################################################################################

Docstring for "pandas.Series.sum" correct. :)
```

@vadakattu can you fix the conflicts? we merged the PR that I mentioned it was touching same code as this one
I believed I dealt with it last night -- the single circle ci failure seems unrelated.
Pulling master again to re-test.

```
=================================== FAILURES ===================================
___________________________ test_tick_add_sub[Milli] ___________________________

cls = <class 'pandas.tseries.offsets.Milli'>

    @pytest.mark.parametrize('cls', tick_classes)
>   @example(n=2, m=3)
    @example(n=800, m=300)
    @example(n=1000, m=5)
    @given(n=st.integers(-999, 999), m=st.integers(-999, 999))
    def test_tick_add_sub(cls, n, m):

pandas/tests/tseries/offsets/test_ticks.py:42: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/opt/conda/envs/pandas-dev/lib/python3.6/site-packages/hypothesis/core.py:552: in execute
    ) % (test.__name__, text_repr[0],))
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <hypothesis.core.StateForActualGivenExecution object at 0x7fb7828ac5f8>
message = 'Hypothesis test_tick_add_sub(cls=Milli, n=0, m=100) produces unreliable results: Falsified on the first call but did not on a subsequent one'

    def __flaky(self, message):
        if len(self.falsifying_examples) <= 1:
>           raise Flaky(message)
E           hypothesis.errors.Flaky: Hypothesis test_tick_add_sub(cls=Milli, n=0, m=100) produces unreliable results: Falsified on the first call but did not on a subsequent one

Tests pass, and docstrings fully compliant per `validate_docstrings`.
@datapythonista seems as if @vadakattu already made the full docs, so there's no point in merging my PR I guess?
I didn't check in detail how much overlap exists in both PRs. But as pointed out in https://github.com/pandas-dev/pandas/pull/23338#issuecomment-443470861, you should talk with @vadakattu and see if it makes sense to have all the changes in one and close the other, or what.
@vadakattu what do you think? I'm fine with taking yours, I don't mine adds much.
👍🏽  Sounds good. 
@vadakattu can you fix the conflicts please. Sorry for the delay.
Conflicts resolved.
Thanks @vadakattu