Repository: pandas-dev/pandas
Pull request: DOC: Capitalize docstring summaries
- [x] closes #23881
- [x] tests added / passed
- [x] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`
- [x] Solves most of the issues raised by the `validate_docstrings.py` script. 

The few issues that still show up on running the script can be attributed to- 
- Docstrings non-existent viz. `tseries.offsets.Tick`, `tseries.offsets.Day` etc. (working on this for a separate PR)
- Auto-generated Doctrings viz. `Series.argmin`, `Timestamp.strptime` etc.
- Docstrings starting with quotes viz. 'Normalizes', 'Unpivots' which were (presumably) added in by the original authors by for a reason.


Problem statement:
DOC: Capitalize docstring summaries
Our standard is to start the docstrings with a capital letter (and finish them with a period).

We'll shortly add a check to make sure that new contributions follow this standard. But before we can do that, we need to fix the many cases that are already wrong.

In this issue we should fix all the remaining cases where the docstring summary starts with a lower case letter. This is the command to generate them (which should return nothing after the fix), and the list of current issues.
```
$ ./scripts/validate_docstrings.py --errors=SS02
pandas.io.json.json_normalize: Summary does not start with a capital letter
pandas.HDFStore.info: Summary does not start with a capital letter
pandas.melt: Summary does not start with a capital letter
pandas.Series.argmin: Summary does not start with a capital letter
pandas.Series.argmax: Summary does not start with a capital letter
pandas.DataFrame.melt: Summary does not start with a capital letter
pandas.DataFrame.to_feather: Summary does not start with a capital letter
pandas.Index.values: Summary does not start with a capital letter
pandas.Index.is_monotonic: Summary does not start with a capital letter
pandas.Index.is_monotonic_increasing: Summary does not start with a capital letter
pandas.Index.is_monotonic_decreasing: Summary does not start with a capital letter
pandas.Index.is_unique: Summary does not start with a capital letter
pandas.Index.dtype: Summary does not start with a capital letter
pandas.Index.dtype_str: Summary does not start with a capital letter
pandas.Index.inferred_type: Summary does not start with a capital letter
pandas.Index.where: Summary does not start with a capital letter
pandas.Index.take: Summary does not start with a capital letter
pandas.Index.putmask: Summary does not start with a capital letter
pandas.Index.ravel: Summary does not start with a capital letter
pandas.Index.join: Summary does not start with a capital letter
pandas.Index.asof_locs: Summary does not start with a capital letter
pandas.Index.contains: Summary does not start with a capital letter
pandas.Index.get_indexer_for: Summary does not start with a capital letter
pandas.RangeIndex.from_range: Summary does not start with a capital letter
pandas.MultiIndex.to_hierarchical: Summary does not start with a capital letter
pandas.Timestamp.ceil: Summary does not start with a capital letter
pandas.Timestamp.combine: Summary does not start with a capital letter
pandas.Timestamp.floor: Summary does not start with a capital letter
pandas.Timestamp.fromordinal: Summary does not start with a capital letter
pandas.Timestamp.fromtimestamp: Summary does not start with a capital letter
pandas.Timestamp.replace: Summary does not start with a capital letter
pandas.Timestamp.strftime: Summary does not start with a capital letter
pandas.Timestamp.strptime: Summary does not start with a capital letter
pandas.Timedelta.view: Summary does not start with a capital letter
pandas.Timedelta.ceil: Summary does not start with a capital letter
pandas.Timedelta.floor: Summary does not start with a capital letter
pandas.Timedelta.to_pytimedelta: Summary does not start with a capital letter
pandas.tseries.offsets.Tick: Summary does not start with a capital letter
pandas.tseries.offsets.Day: Summary does not start with a capital letter
pandas.tseries.offsets.Hour: Summary does not start with a capital letter
pandas.tseries.offsets.Minute: Summary does not start with a capital letter
pandas.tseries.offsets.Second: Summary does not start with a capital letter
pandas.tseries.offsets.Milli: Summary does not start with a capital letter
pandas.tseries.offsets.Micro: Summary does not start with a capital letter
pandas.tseries.offsets.Nano: Summary does not start with a capital letter
pandas.core.window.Rolling.max: Summary does not start with a capital letter
pandas.core.window.Rolling.cov: Summary does not start with a capital letter
pandas.core.window.Rolling.apply: Summary does not start with a capital letter
pandas.core.window.Rolling.quantile: Summary does not start with a capital letter
pandas.core.window.Expanding.max: Summary does not start with a capital letter
pandas.core.window.Expanding.cov: Summary does not start with a capital letter
pandas.core.window.Expanding.apply: Summary does not start with a capital letter
pandas.core.window.Expanding.quantile: Summary does not start with a capital letter
pandas.core.window.EWM.mean: Summary does not start with a capital letter
pandas.core.window.EWM.std: Summary does not start with a capital letter
pandas.core.window.EWM.var: Summary does not start with a capital letter
pandas.core.window.EWM.corr: Summary does not start with a capital letter
pandas.core.window.EWM.cov: Summary does not start with a capital letter
pandas.core.groupby.GroupBy.groups: Summary does not start with a capital letter
pandas.core.groupby.GroupBy.indices: Summary does not start with a capital letter
pandas.core.resample.Resampler.groups: Summary does not start with a capital letter
pandas.core.resample.Resampler.indices: Summary does not start with a capital letter
pandas.core.resample.Resampler.asfreq: Summary does not start with a capital letter
pandas.io.formats.style.Styler.clear: Summary does not start with a capital letter
pandas.Panel.items: Summary does not start with a capital letter
pandas.Panel.major_axis: Summary does not start with a capital letter
pandas.Panel.minor_axis: Summary does not start with a capital letter
```

Ignore `Series.argmin` and `Series.argmax`, as the docstring is autogenerated, and it's not trivial to fix. And other similar cases, if any.

In some cases the problem is that there is a deprecated directive `.. deprecated::` at the beginning of te docstring. This is wrong too, and the deprecation should be after the short summary (the first line/paragraph of the summary).

While this issue is mainly to make the first letter in the summary a capital letter, for the cases where we fix this, would be nice to also add a period at the end of the paragraph, if there is not got one already.

Hints from issue discussion:
@datapythonista let me fix it

Commit message: Another missed PEP8 issue fixed.

Patch to review:
diff --git a/pandas/core/frame.py b/pandas/core/frame.py
index 8d089ab3a1949..9683ea0e69584 100644
--- a/pandas/core/frame.py
+++ b/pandas/core/frame.py
@@ -1953,7 +1953,7 @@ def to_stata(self, fname, convert_dates=None, write_index=True,
 
     def to_feather(self, fname):
         """
-        write out the binary feather-format for DataFrames
+        Write out the binary feather-format for DataFrames.
 
         .. versionadded:: 0.20.0
 
@@ -5839,7 +5839,7 @@ def unstack(self, level=-1, fill_value=None):
         return unstack(self, level, fill_value)
 
     _shared_docs['melt'] = ("""
-    "Unpivots" a DataFrame from wide format to long format, optionally
+    'Unpivots' a DataFrame from wide format to long format, optionally
     leaving identifier variables set.
 
     This function is useful to massage a DataFrame into a format where one
@@ -6045,7 +6045,7 @@ def _gotitem(self,
                  ):
         # type: (...) -> Union[Series, DataFrame]
         """
-        sub-classes to define
+        Sub-classes to define
         return a sliced object
 
         Parameters
diff --git a/pandas/core/groupby/base.py b/pandas/core/groupby/base.py
index 1bf97690a84ed..60ce08b9a6da5 100644
--- a/pandas/core/groupby/base.py
+++ b/pandas/core/groupby/base.py
@@ -12,11 +12,11 @@
 
 
 class GroupByMixin(object):
-    """ provide the groupby facilities to the mixed object """
+    """ Provide the groupby facilities to the mixed object. """
 
     @staticmethod
     def _dispatch(name, *args, **kwargs):
-        """ dispatch to apply """
+        """ Dispatch to apply. """
 
         def outer(self, *args, **kwargs):
             def f(x):
@@ -28,8 +28,8 @@ def f(x):
 
     def _gotitem(self, key, ndim, subset=None):
         """
-        sub-classes to define
-        return a sliced object
+        Sub-classes to define
+        return a sliced object.
 
         Parameters
         ----------
diff --git a/pandas/core/groupby/groupby.py b/pandas/core/groupby/groupby.py
index b68fdf853ab19..30eb6d24443c2 100644
--- a/pandas/core/groupby/groupby.py
+++ b/pandas/core/groupby/groupby.py
@@ -291,7 +291,7 @@ class providing the base-class of operations.
 
 class GroupByPlot(PandasObject):
     """
-    Class implementing the .plot attribute for groupby objects
+    Class implementing the .plot attribute for groupby objects.
     """
 
     def __init__(self, groupby):
@@ -314,7 +314,7 @@ def f(self):
 @contextmanager
 def _group_selection_context(groupby):
     """
-    set / reset the _group_selection_context
+    Set / reset the _group_selection_context.
     """
     groupby._set_group_selection()
     yield groupby
@@ -377,14 +377,14 @@ def __unicode__(self):
 
     def _assure_grouper(self):
         """
-        we create the grouper on instantiation
-        sub-classes may have a different policy
+        We create the grouper on instantiation
+        sub-classes may have a different policy.
         """
         pass
 
     @property
     def groups(self):
-        """ dict {group name -> group labels} """
+        """ Dict {group name -> group labels} """
         self._assure_grouper()
         return self.grouper.groups
 
@@ -395,14 +395,14 @@ def ngroups(self):
 
     @property
     def indices(self):
-        """ dict {group name -> group indices} """
+        """ Dict {group name -> group indices} """
         self._assure_grouper()
         return self.grouper.indices
 
     def _get_indices(self, names):
         """
-        safe get multiple indices, translate keys for
-        datelike to underlying repr
+        Safe get multiple indices, translate keys for
+        datelike to underlying repr.
         """
 
         def get_converter(s):
@@ -450,7 +450,7 @@ def get_converter(s):
         return [self.indices.get(name, []) for name in names]
 
     def _get_index(self, name):
-        """ safe get index, translate keys for datelike to underlying repr """
+        """ Safe get index, translate keys for datelike to underlying repr ."""
         return self._get_indices([name])[0]
 
     @cache_readonly
@@ -1127,7 +1127,7 @@ def mean(self, *args, **kwargs):
     @Appender(_doc_template)
     def median(self, **kwargs):
         """
-        Compute median of groups, excluding missing values
+        Compute median of groups, excluding missing values.
 
         For multiple groupings, the result index will be a MultiIndex
         """
@@ -1148,9 +1148,9 @@ def f(x):
     @Appender(_doc_template)
     def std(self, ddof=1, *args, **kwargs):
         """
-        Compute standard deviation of groups, excluding missing values
+        Compute standard deviation of groups, excluding missing values.
 
-        For multiple groupings, the result index will be a MultiIndex
+        For multiple groupings, the result index will be a MultiIndex.
 
         Parameters
         ----------
@@ -1166,9 +1166,9 @@ def std(self, ddof=1, *args, **kwargs):
     @Appender(_doc_template)
     def var(self, ddof=1, *args, **kwargs):
         """
-        Compute variance of groups, excluding missing values
+        Compute variance of groups, excluding missing values.
 
-        For multiple groupings, the result index will be a MultiIndex
+        For multiple groupings, the result index will be a MultiIndex.
 
         Parameters
         ----------
@@ -1192,9 +1192,9 @@ def var(self, ddof=1, *args, **kwargs):
     @Appender(_doc_template)
     def sem(self, ddof=1):
         """
-        Compute standard error of the mean of groups, excluding missing values
+        Compute standard error of the mean of groups, excluding missing values.
 
-        For multiple groupings, the result index will be a MultiIndex
+        For multiple groupings, the result index will be a MultiIndex.
 
         Parameters
         ----------
diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py
index 28aefb652adb0..73db22e20c5f0 100644
--- a/pandas/core/indexes/base.py
+++ b/pandas/core/indexes/base.py
@@ -690,17 +690,17 @@ def __array_wrap__(self, result, context=None):
 
     @cache_readonly
     def dtype(self):
-        """ return the dtype object of the underlying data """
+        """ Return the dtype object of the underlying data. """
         return self._data.dtype
 
     @cache_readonly
     def dtype_str(self):
-        """ return the dtype str of the underlying data """
+        """ Return the dtype str of the underlying data. """
         return str(self.dtype)
 
     @property
     def values(self):
-        """ return the underlying data as an ndarray """
+        """ Return the underlying data as an ndarray. """
         return self._data.view(np.ndarray)
 
     @property
@@ -825,12 +825,12 @@ def repeat(self, repeats, *args, **kwargs):
         return self._shallow_copy(self._values.repeat(repeats))
 
     _index_shared_docs['where'] = """
-        .. versionadded:: 0.19.0
-
         Return an Index of same shape as self and whose corresponding
         entries are from self where cond is True and otherwise are from
         other.
 
+        .. versionadded:: 0.19.0
+
         Parameters
         ----------
         cond : boolean array-like with the same length as self
@@ -862,7 +862,7 @@ def where(self, cond, other=None):
 
     def ravel(self, order='C'):
         """
-        return an ndarray of the flattened values of the underlying data
+        Return an ndarray of the flattened values of the underlying data.
 
         See Also
         --------
@@ -1493,13 +1493,14 @@ def _mpl_repr(self):
     # introspection
     @property
     def is_monotonic(self):
-        """ alias for is_monotonic_increasing (deprecated) """
+        """ Alias for is_monotonic_increasing.
+        .. deprecated :: """
         return self.is_monotonic_increasing
 
     @property
     def is_monotonic_increasing(self):
         """
-        return if the index is monotonic increasing (only equal or
+        Return if the index is monotonic increasing (only equal or
         increasing) values.
 
         Examples
@@ -1516,7 +1517,7 @@ def is_monotonic_increasing(self):
     @property
     def is_monotonic_decreasing(self):
         """
-        return if the index is monotonic decreasing (only equal or
+        Return if the index is monotonic decreasing (only equal or
         decreasing) values.
 
         Examples
@@ -1532,8 +1533,8 @@ def is_monotonic_decreasing(self):
 
     @property
     def _is_strictly_monotonic_increasing(self):
-        """return if the index is strictly monotonic increasing
-        (only increasing) values
+        """Return if the index is strictly monotonic increasing
+        (only increasing) values.
 
         Examples
         --------
@@ -1548,8 +1549,8 @@ def _is_strictly_monotonic_increasing(self):
 
     @property
     def _is_strictly_monotonic_decreasing(self):
-        """return if the index is strictly monotonic decreasing
-        (only decreasing) values
+        """Return if the index is strictly monotonic decreasing
+        (only decreasing) values.
 
         Examples
         --------
@@ -1567,7 +1568,7 @@ def is_lexsorted_for_tuple(self, tup):
 
     @cache_readonly
     def is_unique(self):
-        """ return if the index has unique values """
+        """ Return if the index has unique values. """
         return self._engine.is_unique
 
     @property
@@ -1958,11 +1959,11 @@ def _get_level_number(self, level):
 
     @cache_readonly
     def inferred_type(self):
-        """ return a string of the type inferred from the values """
+        """ Return a string of the type inferred from the values, """
         return lib.infer_dtype(self)
 
     def _is_memory_usage_qualified(self):
-        """ return a boolean if we need a qualified .info display """
+        """ Return a boolean if we need a qualified .info display. """
         return self.is_object()
 
     def is_type_compatible(self, kind):
@@ -1980,7 +1981,7 @@ def __reduce__(self):
         return _new_Index, (self.__class__, d), None
 
     def __setstate__(self, state):
-        """Necessary for making this object picklable"""
+        """ Necessary for making this object picklable. """
 
         if isinstance(state, dict):
             self._data = state.pop('data')
@@ -2014,7 +2015,7 @@ def __nonzero__(self):
     __bool__ = __nonzero__
 
     _index_shared_docs['__contains__'] = """
-        return a boolean if this key is IN the index
+        Return a boolean if this key is IN the index.
 
         Parameters
         ----------
@@ -2034,7 +2035,7 @@ def __contains__(self, key):
             return False
 
     _index_shared_docs['contains'] = """
-        return a boolean if this key is IN the index
+        Return a boolean if this key is IN the index.
 
         Parameters
         ----------
@@ -2152,7 +2153,7 @@ def _concat_same_dtype(self, to_concat, name):
         return _concat._concat_index_asobject(to_concat, name)
 
     _index_shared_docs['take'] = """
-        return a new %(klass)s of the values selected by the indices
+        Return a new %(klass)s of the values selected by the indices.
 
         For internal compatibility with numpy arrays.
 
@@ -2345,7 +2346,7 @@ def notna(self):
 
     def putmask(self, mask, value):
         """
-        return a new Index of the values set with the mask
+        Return a new Index of the values set with the mask.
 
         See Also
         --------
@@ -2536,12 +2537,17 @@ def asof(self, label):
 
     def asof_locs(self, where, mask):
         """
-        where : array of timestamps
-        mask : array of booleans where data is not NA
+        Parameters
+        ----------
+        where : array
+            Array of timestamps.
+        mask : array-like
+            Array of booleans denoting where values in the original
+            data are not NA.
         """
         locs = self.values[mask].searchsorted(where.values, side='right')
-
         locs = np.where(locs > 0, locs - 1, 0)
+
         result = np.arange(len(self))[mask].take(locs)
 
         first = mask.argmax()
@@ -3501,8 +3507,9 @@ def get_indexer_non_unique(self, target):
 
     def get_indexer_for(self, target, **kwargs):
         """
-        guaranteed return of an indexer even when non-unique
-        This dispatches to get_indexer or get_indexer_nonunique as appropriate
+        Guaranteed return of an indexer even when non-unique.
+        This dispatches to get_indexer or get_indexer_nonunique
+        as appropriate.
         """
         if self.is_unique:
             return self.get_indexer(target, **kwargs)
@@ -3818,11 +3825,11 @@ def _reindex_non_unique(self, target):
         return new_index, indexer, new_indexer
 
     _index_shared_docs['join'] = """
-        *this is an internal non-public method*
-
         Compute join_index and indexers to conform data
         structures to the new index.
 
+        *This is an internal non-public method*
+
         Parameters
         ----------
         other : Index
@@ -4281,9 +4288,9 @@ def _maybe_cast_indexer(self, key):
 
     def _validate_indexer(self, form, key, kind):
         """
-        if we are positional indexer
+        If we are positional indexer
         validate that we have appropriate typed bounds
-        must be an integer
+        must be an integer.
         """
         assert kind in ['ix', 'loc', 'getitem', 'iloc']
 
@@ -4493,7 +4500,7 @@ def slice_locs(self, start=None, end=None, step=None, kind=None):
 
     def delete(self, loc):
         """
-        Make new Index with passed location(-s) deleted
+        Make new Index with passed location(-s) deleted.
 
         Returns
         -------
@@ -4504,7 +4511,7 @@ def delete(self, loc):
     def insert(self, loc, item):
         """
         Make new Index inserting new item at location. Follows
-        Python list.append semantics for negative values
+        Python list.append semantics for negative values.
 
         Parameters
         ----------
@@ -4522,7 +4529,7 @@ def insert(self, loc, item):
 
     def drop(self, labels, errors='raise'):
         """
-        Make new Index with passed list of labels deleted
+        Make new Index with passed list of labels deleted.
 
         Parameters
         ----------
diff --git a/pandas/core/indexes/datetimelike.py b/pandas/core/indexes/datetimelike.py
index 1179f6f39d06c..cb09998331832 100644
--- a/pandas/core/indexes/datetimelike.py
+++ b/pandas/core/indexes/datetimelike.py
@@ -34,7 +34,7 @@
 
 
 class DatelikeOps(object):
-    """ common ops for DatetimeIndex/PeriodIndex, but not TimedeltaIndex """
+    """ Common ops for DatetimeIndex/PeriodIndex, but not TimedeltaIndex. """
 
     def strftime(self, date_format):
         return Index(self.format(date_format=date_format),
@@ -76,7 +76,7 @@ def strftime(self, date_format):
 
 
 class TimelikeOps(object):
-    """ common ops for TimedeltaIndex/DatetimeIndex, but not PeriodIndex """
+    """ Common ops for TimedeltaIndex/DatetimeIndex, but not PeriodIndex. """
 
     _round_doc = (
         """
diff --git a/pandas/core/indexes/multi.py b/pandas/core/indexes/multi.py
index f9483b48b5261..ea6dfa6a3a6af 100644
--- a/pandas/core/indexes/multi.py
+++ b/pandas/core/indexes/multi.py
@@ -121,7 +121,7 @@ def _codes_to_ints(self, codes):
 
 class MultiIndex(Index):
     """
-    A multi-level, or hierarchical, index object for pandas objects
+    A multi-level, or hierarchical, index object for pandas objects.
 
     Parameters
     ----------
@@ -1195,14 +1195,14 @@ def to_frame(self, index=True, name=None):
 
     def to_hierarchical(self, n_repeat, n_shuffle=1):
         """
-        .. deprecated:: 0.24.0
-
         Return a MultiIndex reshaped to conform to the
         shapes given by n_repeat and n_shuffle.
 
         Useful to replicate and rearrange a MultiIndex for combination
         with another Index with n_repeat items.
 
+        .. deprecated:: 0.24.0
+
         Parameters
         ----------
         n_repeat : int
diff --git a/pandas/core/indexes/range.py b/pandas/core/indexes/range.py
index 0d4e7aaebeca5..d6286244fcb7e 100644
--- a/pandas/core/indexes/range.py
+++ b/pandas/core/indexes/range.py
@@ -122,7 +122,7 @@ def ensure_int(value, field):
 
     @classmethod
     def from_range(cls, data, name=None, dtype=None, **kwargs):
-        """ create RangeIndex from a range (py3), or xrange (py2) object """
+        """ Create RangeIndex from a range (py3), or xrange (py2) object. """
         if not isinstance(data, range):
             raise TypeError(
                 '{0}(...) must be called with object coercible to a '
diff --git a/pandas/core/panel.py b/pandas/core/panel.py
index 90016f599addc..cd3cb192e4588 100644
--- a/pandas/core/panel.py
+++ b/pandas/core/panel.py
@@ -157,7 +157,7 @@ def __init__(self, data=None, items=None, major_axis=None, minor_axis=None,
     def _init_data(self, data, copy, dtype, **kwargs):
         """
         Generate ND initialization; axes are passed
-        as required objects to __init__
+        as required objects to __init__.
         """
         if data is None:
             data = {}
@@ -242,7 +242,7 @@ def _init_arrays(self, arrays, arr_names, axes):
     @classmethod
     def from_dict(cls, data, intersect=False, orient='items', dtype=None):
         """
-        Construct Panel from dict of DataFrame objects
+        Construct Panel from dict of DataFrame objects.
 
         Parameters
         ----------
@@ -348,7 +348,7 @@ def _compare_constructor(self, other, func):
 
     def __unicode__(self):
         """
-        Return a string representation for a particular Panel
+        Return a string representation for a particular Panel.
 
         Invoked by unicode(df) in py2 only.
         Yields a Unicode String in both py2/py3.
@@ -377,7 +377,7 @@ def _get_plane_axes_index(self, axis):
         """
         Get my plane axes indexes: these are already
         (as compared with higher level planes),
-        as we are returning a DataFrame axes indexes
+        as we are returning a DataFrame axes indexes.
         """
         axis_name = self._get_axis_name(axis)
 
@@ -397,7 +397,7 @@ def _get_plane_axes(self, axis):
         """
         Get my plane axes indexes: these are already
         (as compared with higher level planes),
-        as we are returning a DataFrame axes
+        as we are returning a DataFrame axes.
         """
         return [self._get_axis(axi)
                 for axi in self._get_plane_axes_index(axis)]
@@ -473,7 +473,8 @@ def as_matrix(self):
     # Getting and setting elements
 
     def get_value(self, *args, **kwargs):
-        """Quickly retrieve single value at (item, major, minor) location
+        """
+        Quickly retrieve single value at (item, major, minor) location.
 
         .. deprecated:: 0.21.0
 
@@ -787,7 +788,7 @@ def _combine_panel(self, other, func):
 
     def major_xs(self, key):
         """
-        Return slice of panel along major axis
+        Return slice of panel along major axis.
 
         Parameters
         ----------
@@ -811,7 +812,7 @@ def major_xs(self, key):
 
     def minor_xs(self, key):
         """
-        Return slice of panel along minor axis
+        Return slice of panel along minor axis.
 
         Parameters
         ----------
@@ -835,7 +836,7 @@ def minor_xs(self, key):
 
     def xs(self, key, axis=1):
         """
-        Return slice of panel along selected axis
+        Return slice of panel along selected axis.
 
         Parameters
         ----------
@@ -898,7 +899,7 @@ def _ixs(self, i, axis=0):
 
     def groupby(self, function, axis='major'):
         """
-        Group data on given axis, returning GroupBy object
+        Group data on given axis, returning GroupBy object.
 
         Parameters
         ----------
@@ -993,7 +994,7 @@ def construct_index_parts(idx, major=True):
 
     def apply(self, func, axis='major', **kwargs):
         """
-        Applies function along axis (or axes) of the Panel
+        Applies function along axis (or axes) of the Panel.
 
         Parameters
         ----------
@@ -1115,7 +1116,7 @@ def _apply_1d(self, func, axis):
         return self._construct_return_type(results, planes)
 
     def _apply_2d(self, func, axis):
-        """ handle 2-d slices, equiv to iterating over the other axis """
+        """ Handle 2-d slices, equiv to iterating over the other axis. """
 
         ndim = self.ndim
         axis = [self._get_axis_number(a) for a in axis]
@@ -1172,7 +1173,7 @@ def _reduce(self, op, name, axis=0, skipna=True, numeric_only=None,
         return self._construct_return_type(result, axes)
 
     def _construct_return_type(self, result, axes=None):
-        """ return the type for the ndim of the result """
+        """ Return the type for the ndim of the result. """
         ndim = getattr(result, 'ndim', None)
 
         # need to assume they are the same
@@ -1333,7 +1334,7 @@ def tshift(self, periods=1, freq=None, axis='major'):
 
     def join(self, other, how='left', lsuffix='', rsuffix=''):
         """
-        Join items with other Panel either on major and minor axes column
+        Join items with other Panel either on major and minor axes column.
 
         Parameters
         ----------
@@ -1440,13 +1441,13 @@ def _get_join_index(self, other, how):
     # miscellaneous data creation
     @staticmethod
     def _extract_axes(self, data, axes, **kwargs):
-        """ return a list of the axis indices """
+        """ Return a list of the axis indices. """
         return [self._extract_axis(self, data, axis=i, **kwargs)
                 for i, a in enumerate(axes)]
 
     @staticmethod
     def _extract_axes_for_slice(self, axes):
-        """ return the slice dictionary for these axes """
+        """ Return the slice dictionary for these axes. """
         return {self._AXIS_SLICEMAP[i]: a for i, a in
                 zip(self._AXIS_ORDERS[self._AXIS_LEN - len(axes):], axes)}
 
diff --git a/pandas/core/resample.py b/pandas/core/resample.py
index 125b441e5558a..1193d932edf86 100644
--- a/pandas/core/resample.py
+++ b/pandas/core/resample.py
@@ -757,8 +757,8 @@ def interpolate(self, method='linear', axis=0, limit=None, inplace=False,
 
     def asfreq(self, fill_value=None):
         """
-        return the values at the new freq,
-        essentially a reindex
+        Return the values at the new freq,
+        essentially a reindex.
 
         Parameters
         ----------
@@ -777,7 +777,7 @@ def asfreq(self, fill_value=None):
 
     def std(self, ddof=1, *args, **kwargs):
         """
-        Compute standard deviation of groups, excluding missing values
+        Compute standard deviation of groups, excluding missing values.
 
         Parameters
         ----------
@@ -789,7 +789,7 @@ def std(self, ddof=1, *args, **kwargs):
 
     def var(self, ddof=1, *args, **kwargs):
         """
-        Compute variance of groups, excluding missing values
+        Compute variance of groups, excluding missing values.
 
         Parameters
         ----------
@@ -909,7 +909,7 @@ def _maybe_process_deprecations(r, how=None, fill_method=None, limit=None):
 
 
 class _GroupByMixin(GroupByMixin):
-    """ provide the groupby facilities """
+    """ Provide the groupby facilities. """
 
     def __init__(self, obj, *args, **kwargs):
 
@@ -931,8 +931,8 @@ def __init__(self, obj, *args, **kwargs):
 
     def _apply(self, f, grouper=None, *args, **kwargs):
         """
-        dispatch to _upsample; we are stripping all of the _upsample kwargs and
-        performing the original function call on the grouped object
+        Dispatch to _upsample; we are stripping all of the _upsample kwargs and
+        performing the original function call on the grouped object.
         """
 
         def func(x):
@@ -966,7 +966,7 @@ def _get_binner_for_time(self):
 
     def _downsample(self, how, **kwargs):
         """
-        Downsample the cython defined function
+        Downsample the cython defined function.
 
         Parameters
         ----------
@@ -1106,7 +1106,7 @@ def _convert_obj(self, obj):
 
     def _downsample(self, how, **kwargs):
         """
-        Downsample the cython defined function
+        Downsample the cython defined function.
 
         Parameters
         ----------
@@ -1177,7 +1177,7 @@ def _upsample(self, method, limit=None, fill_value=None):
 
 class PeriodIndexResamplerGroupby(_GroupByMixin, PeriodIndexResampler):
     """
-    Provides a resample of a groupby implementation
+    Provides a resample of a groupby implementation.
 
     .. versionadded:: 0.18.1
 
@@ -1207,7 +1207,7 @@ def _adjust_binner_for_upsample(self, binner):
 
 class TimedeltaIndexResamplerGroupby(_GroupByMixin, TimedeltaIndexResampler):
     """
-    Provides a resample of a groupby implementation
+    Provides a resample of a groupby implementation.
 
     .. versionadded:: 0.18.1
 
@@ -1218,7 +1218,7 @@ def _constructor(self):
 
 
 def resample(obj, kind=None, **kwds):
-    """ create a TimeGrouper and return our resampler """
+    """ Create a TimeGrouper and return our resampler. """
     tg = TimeGrouper(**kwds)
     return tg._get_resampler(obj, kind=kind)
 
@@ -1244,7 +1244,7 @@ def get_resampler_for_grouping(groupby, rule, how=None, fill_method=None,
 
 class TimeGrouper(Grouper):
     """
-    Custom groupby class for time-interval grouping
+    Custom groupby class for time-interval grouping.
 
     Parameters
     ----------
diff --git a/pandas/core/window.py b/pandas/core/window.py
index 4c67b04e89ba8..47914cd40ec85 100644
--- a/pandas/core/window.py
+++ b/pandas/core/window.py
@@ -161,7 +161,7 @@ def _window_type(self):
         return self.__class__.__name__
 
     def __unicode__(self):
-        """ provide a nice str repr of our rolling object """
+        """ Provide a nice str repr of our rolling object. """
 
         attrs = ["{k}={v}".format(k=k, v=getattr(self, k))
                  for k in self._attributes
@@ -175,7 +175,7 @@ def __iter__(self):
 
     def _get_index(self, index=None):
         """
-        Return index as ndarrays
+        Return index as ndarrays.
 
         Returns
         -------
@@ -776,8 +776,8 @@ def __init__(self, obj, *args, **kwargs):
     def _apply(self, func, name, window=None, center=None,
                check_minp=None, **kwargs):
         """
-        dispatch to apply; we are stripping all of the _apply kwargs and
-        performing the original function call on the grouped object
+        Dispatch to apply; we are stripping all of the _apply kwargs and
+        performing the original function call on the grouped object.
         """
 
         def f(x, name=name, *args):
@@ -995,7 +995,7 @@ def sum(self, *args, **kwargs):
         return self._apply('roll_sum', 'sum', **kwargs)
 
     _shared_docs['max'] = dedent("""
-    %(name)s maximum
+    Calculate the %(name)s maximum
     """)
 
     def max(self, *args, **kwargs):
@@ -1259,7 +1259,7 @@ def kurt(self, **kwargs):
                            check_minp=_require_min_periods(4), **kwargs)
 
     _shared_docs['quantile'] = dedent("""
-    %(name)s quantile.
+    Calculate the %(name)s quantile.
 
     Parameters
     ----------
@@ -1333,7 +1333,7 @@ def f(arg, *args, **kwargs):
                            **kwargs)
 
     _shared_docs['cov'] = dedent("""
-    %(name)s sample covariance
+    Calculate the %(name)s sample covariance
 
     Parameters
     ----------
@@ -1760,7 +1760,7 @@ def corr(self, other=None, pairwise=None, **kwargs):
 
 class RollingGroupby(_GroupByMixin, Rolling):
     """
-    Provides a rolling groupby implementation
+    Provides a rolling groupby implementation.
 
     .. versionadded:: 0.18.1
 
@@ -1781,7 +1781,7 @@ def _gotitem(self, key, ndim, subset=None):
 
     def _validate_monotonic(self):
         """
-        validate that on is monotonic;
+        Validate that on is monotonic;
         we don't care for groupby.rolling
         because we have already validated at a higher
         level
@@ -2031,7 +2031,7 @@ def corr(self, other=None, pairwise=None, **kwargs):
 
 class ExpandingGroupby(_GroupByMixin, Expanding):
     """
-    Provides a expanding groupby implementation
+    Provides a expanding groupby implementation.
 
     .. versionadded:: 0.18.1
 
@@ -2069,7 +2069,7 @@ def _constructor(self):
 
 class EWM(_Rolling):
     r"""
-    Provides exponential weighted functions
+    Provides exponential weighted functions.
 
     .. versionadded:: 0.18.0
 
@@ -2219,7 +2219,8 @@ def aggregate(self, arg, *args, **kwargs):
     agg = aggregate
 
     def _apply(self, func, **kwargs):
-        """Rolling statistical measure using supplied function. Designed to be
+        """
+        Rolling statistical measure using supplied function. Designed to be
         used with passed-in Cython array-based functions.
 
         Parameters
@@ -2261,7 +2262,7 @@ def func(arg):
     @Substitution(name='ewm')
     @Appender(_doc_template)
     def mean(self, *args, **kwargs):
-        """exponential weighted moving average"""
+        """ Exponential weighted moving average. """
         nv.validate_window_func('mean', args, kwargs)
         return self._apply('ewma', **kwargs)
 
@@ -2269,7 +2270,7 @@ def mean(self, *args, **kwargs):
     @Appender(_doc_template)
     @Appender(_bias_template)
     def std(self, bias=False, *args, **kwargs):
-        """exponential weighted moving stddev"""
+        """ Exponential weighted moving stddev. """
         nv.validate_window_func('std', args, kwargs)
         return _zsqrt(self.var(bias=bias, **kwargs))
 
@@ -2279,7 +2280,7 @@ def std(self, bias=False, *args, **kwargs):
     @Appender(_doc_template)
     @Appender(_bias_template)
     def var(self, bias=False, *args, **kwargs):
-        """exponential weighted moving variance"""
+        """ Exponential weighted moving variance. """
         nv.validate_window_func('var', args, kwargs)
 
         def f(arg):
@@ -2293,7 +2294,7 @@ def f(arg):
     @Appender(_doc_template)
     @Appender(_pairwise_template)
     def cov(self, other=None, pairwise=None, bias=False, **kwargs):
-        """exponential weighted sample covariance"""
+        """ Exponential weighted sample covariance. """
         if other is None:
             other = self._selected_obj
             # only default unset
@@ -2316,7 +2317,7 @@ def _get_cov(X, Y):
     @Appender(_doc_template)
     @Appender(_pairwise_template)
     def corr(self, other=None, pairwise=None, **kwargs):
-        """exponential weighted sample correlation"""
+        """ Exponential weighted sample correlation. """
         if other is None:
             other = self._selected_obj
             # only default unset
diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py
index 2c018598a6a6e..4cb372525ce10 100644
--- a/pandas/io/formats/style.py
+++ b/pandas/io/formats/style.py
@@ -417,7 +417,8 @@ def format(self, formatter, subset=None):
         return self
 
     def render(self, **kwargs):
-        """Render the built up styles to HTML
+        """
+        Render the built up styles to HTML.
 
         Parameters
         ----------
@@ -504,7 +505,8 @@ def __deepcopy__(self, memo):
         return self._copy(deepcopy=True)
 
     def clear(self):
-        """"Reset" the styler, removing any previously applied styles.
+        """
+        'Reset' the styler, removing any previously applied styles.
         Returns None.
         """
         self.ctx.clear()
diff --git a/pandas/io/json/normalize.py b/pandas/io/json/normalize.py
index 3e3f125b56d88..4cabbe614a0a7 100644
--- a/pandas/io/json/normalize.py
+++ b/pandas/io/json/normalize.py
@@ -24,9 +24,9 @@ def _convert_to_line_delimits(s):
 
 
 def nested_to_record(ds, prefix="", sep=".", level=0):
-    """a simplified json_normalize
+    """A simplified json_normalize.
 
-    converts a nested dict into a flat dict ("record"), unlike json_normalize,
+    Converts a nested dict into a flat dict ("record"), unlike json_normalize,
     it does not attempt to extract a subset of the data.
 
     Parameters
@@ -99,7 +99,7 @@ def json_normalize(data, record_path=None, meta=None,
                    errors='raise',
                    sep='.'):
     """
-    "Normalize" semi-structured JSON data into a flat table
+    'Normalize' semi-structured JSON data into a flat table.
 
     Parameters
     ----------
diff --git a/pandas/io/pytables.py b/pandas/io/pytables.py
index ab1c89ef828d0..640034cb49d25 100644
--- a/pandas/io/pytables.py
+++ b/pandas/io/pytables.py
@@ -414,7 +414,7 @@ def _is_metadata_of(group, parent_group):
 class HDFStore(StringMixin):
 
     """
-    dict-like IO interface for storing pandas objects in PyTables
+    Dict-like IO interface for storing pandas objects in PyTables
     either Fixed or Table format.
 
     Parameters
@@ -1217,7 +1217,7 @@ def copy(self, file, mode='w', propindexes=True, keys=None, complib=None,
 
     def info(self):
         """
-        print detailed information on the store
+        Print detailed information on the store.
 
         .. versionadded:: 0.21.0
         """


Code review comments:
diff_hunk: @@ -12,11 +12,11 @@
 
 
 class GroupByMixin(object):
-    """ provide the groupby facilities to the mixed object """
+    """ Provide the groupby facilities to the mixed object. """
path: pandas/core/groupby/base.py
text: @user1:
Do you mind changing all the cases like this (quotes in the same line) to this:
```
"""
Provide the groupby facilities to the mixed object.
"""
```
This will fail the validation soon too, so if you don't mind changing the edited ones, it'd be great.

@author:
Sorry, the formatting is slightly unclear - it shows no change from what I've already added in. Did you mean to say I should move it to a new line?

@user1:
sorry, I did a mistake with the fithib formatting, amd wasn't rendering as I intended. I editted the comment, you can see now what I meant

diff_hunk: @@ -5839,7 +5839,7 @@ def unstack(self, level=-1, fill_value=None):
         return unstack(self, level, fill_value)
 
     _shared_docs['melt'] = ("""
-    "Unpivots" a DataFrame from wide format to long format, optionally
+    'Unpivots' a DataFrame from wide format to long format, optionally
path: pandas/core/frame.py
text: @user1:
I think we can simply remove the quotes. But in any case, we should fix the validation script to not report cases where the first character is not a letter.

@author:
So, which fix should I make? Removing the quotes or fixing the validation script? Or both?

@user1:
in this PR remove the quotes, if you want to change the script, that should be im a separate PR

diff_hunk: @@ -504,7 +505,8 @@ def __deepcopy__(self, memo):
         return self._copy(deepcopy=True)
 
     def clear(self):
-        """"Reset" the styler, removing any previously applied styles.
+        """
+        'Reset' the styler, removing any previously applied styles.
path: pandas/io/formats/style.py
text: @user1:
I'd remove the quotes here too.