DOC: Inline docstrings of a batch of functions in `pandas/core/groupby/groupby.py`

retry

- [ ] closes #62437 (Replace xxxx with the GitHub issue number)
- [ ] [Tests added and passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#writing-tests) if fixing a bug or adding a new feature
- [x] All [code checks passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#pre-commit).
- [ ] Added [type annotations](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#type-hints) to new arguments/methods/functions.
- [ ] Added an entry in the latest `doc/source/whatsnew/vX.X.X.rst` file if fixing a bug or adding a new feature.
- [ ] If I used AI to develop this pull request, I prompted it to follow `AGENTS.md`.

@@ -158,14 +158,6 @@ class providing the base-class of operations.
         RollingGroupby,
     )

-_common_see_also = """
-        See Also
-        --------
-        Series.%(name)s : Apply a function %(name)s to a Series.
-        DataFrame.%(name)s : Apply a function %(name)s
-            to each row or column of a DataFrame.
-"""
-
 _groupby_agg_method_engine_template = """
 Compute {fname} of group values.

@@ -1975,8 +1967,6 @@ def _obj_1d_constructor(self) -> Callable:
         return self.obj._constructor

     [USER_REDACTED]
-    [USER_REDACTED](name="groupby")
-    [USER_REDACTED](see_also=_common_see_also)
     def any(self, skipna: bool = True) -> NDFrameT:
         """
         [NAME_REDACTED] if any value in the group is truthful, else False.
@@ -1991,7 +1981,12 @@ def any(self, skipna: bool = True) -> NDFrameT:
         Series or [NAME_REDACTED] or Series of boolean values, where a value is True if any element
             is True within its respective group, False otherwise.
-        %(see_also)s
+
+        See Also
+        --------
+        Series.any : Apply function any to a Series.
+        DataFrame.any : Apply function any to each row or column of a DataFrame.
+
         Examples
         --------
         For SeriesGroupBy:
@@ -2032,8 +2027,6 @@ def any(self, skipna: bool = True) -> NDFrameT:
         )

     [USER_REDACTED]
-    [USER_REDACTED](name="groupby")
-    [USER_REDACTED](see_also=_common_see_also)
     def all(self, skipna: bool = True) -> NDFrameT:
         """
         [NAME_REDACTED] if all values in the group are truthful, else False.
@@ -2048,7 +2041,12 @@ def all(self, skipna: bool = True) -> NDFrameT:
         Series or [NAME_REDACTED] or Series of boolean values, where a value is True if all elements
             are True within its respective group, False otherwise.
-        %(see_also)s
+
+        See Also
+        --------
+        Series.all : Apply function all to a Series.
+        DataFrame.all : Apply function all to each row or column of a DataFrame.
+
         Examples
         --------

@@ -2090,8 +2088,6 @@ def all(self, skipna: bool = True) -> NDFrameT:
         )

     [USER_REDACTED]
-    [USER_REDACTED](name="groupby")
-    [USER_REDACTED](see_also=_common_see_also)
     def count(self) -> NDFrameT:
         """
         Compute count of group, excluding missing values.
@@ -2100,7 +2096,12 @@ def count(self) -> NDFrameT:
         -------
         Series or [NAME_REDACTED] of values within each group.
-        %(see_also)s
+
+        See Also
+        --------
+        Series.count : Apply function count to a Series.
+        DataFrame.count : Apply function count to each row or column of a DataFrame.
+
         Examples
         --------
         For SeriesGroupBy:
@@ -2191,8 +2192,6 @@ def hfunc(bvalues: ArrayLike) -> ArrayLike:
         return result

     [USER_REDACTED]
-    [USER_REDACTED](name="groupby")
-    [USER_REDACTED](see_also=_common_see_also)
     def mean(
         self,
         numeric_only: bool = False,
@@ -2232,7 +2231,12 @@ def mean(
         -------
         pandas.Series or pandas.[NAME_REDACTED] of values within each group. Same object type as the caller.
-        %(see_also)s
+
+        See Also
+        --------
+        Series.mean : Apply function mean to a Series.
+        DataFrame.mean : Apply function mean to each row or column of a DataFrame.
+
         Examples
         --------
         >>> df = pd.DataFrame(
@@ -2318,9 +2322,8 @@ def median(self, numeric_only: bool = False, skipna: bool = True) -> NDFrameT:

         See Also
         --------
-        Series.groupby : Apply a function groupby to a Series.
-        DataFrame.groupby : Apply a function groupby to each row or column of a
-            DataFrame.
+        Series.median : Apply function median to a Series.
+        DataFrame.median : Apply function median to each row or column of a DataFrame.

         Examples
         --------
@@ -2392,8 +2395,6 @@ def median(self, numeric_only: bool = False, skipna: bool = True) -> NDFrameT:
         return result.__finalize__(self.obj, method="groupby")

     [USER_REDACTED]
-    [USER_REDACTED](name="groupby")
-    [USER_REDACTED](see_also=_common_see_also)
     def std(
         self,
         ddof: int = 1,
@@ -2442,7 +2443,12 @@ def std(
         -------
         Series or [NAME_REDACTED] deviation of values within each group.
-        %(see_also)s
+
+        See Also
+        --------
+        Series.std : Apply function std to a Series.
+        DataFrame.std : Apply function std to each row or column of a DataFrame.
+
         Examples
         --------
         For SeriesGroupBy:
@@ -2505,8 +2511,6 @@ def std(
             )

     [USER_REDACTED]
-    [USER_REDACTED](name="groupby")
-    [USER_REDACTED](see_also=_common_see_also)
     def var(
         self,
         ddof: int = 1,
@@ -2554,7 +2558,12 @@ def var(
         -------
         Series or [NAME_REDACTED] of values within each group.
-        %(see_also)s
+
+        See Also
+        --------
+        Series.var : Apply function var to a Series.
+        DataFrame.var : Apply function var to each row or column of a DataFrame.
+
         Examples
         --------
         For SeriesGroupBy:
@@ -2846,8 +2855,6 @@ def sem(
         )

     [USER_REDACTED]
-    [USER_REDACTED](name="groupby")
-    [USER_REDACTED](see_also=_common_see_also)
     def size(self) -> DataFrame | Series:
         """
         Compute group sizes.
@@ -2857,7 +2864,12 @@ def size(self) -> DataFrame | Series:
         DataFrame or [NAME_REDACTED] of rows in each group as a Series if as_index is True
             or a DataFrame if as_index is False.
-        %(see_also)s
+
+        See Also
+        --------
+        Series.size : Apply function size to a Series.
+        DataFrame.size : Apply function size to each row or column of a DataFrame.
+
         Examples
         --------

@@ -4252,8 +4264,6 @@ def bfill(self, limit: int | None = None):

     [USER_REDACTED]
     [USER_REDACTED]
-    [USER_REDACTED](name="groupby")
-    [USER_REDACTED](see_also=_common_see_also)
     def nth(self) -> GroupByNthSelector:
         """
         Take the nth row from each group if n is an int, otherwise a subset of rows.
@@ -4269,7 +4279,12 @@ def nth(self) -> GroupByNthSelector:
         -------
         Series or DataFrame
             N-th value within each group.
-        %(see_also)s
+
+        See Also
+        --------
+        Series.nth : Apply function nth to a Series.
+        DataFrame.nth : Apply function nth to each row or column of a DataFrame.
+
         Examples
         --------

@@ -4751,8 +4766,6 @@ def cumcount(self, ascending: bool = True):
         return self._obj_1d_constructor(cumcounts, index)

     [USER_REDACTED]
-    [USER_REDACTED](name="groupby")
-    [USER_REDACTED](see_also=_common_see_also)
     def rank(
         self,
         method: str = "average",
@@ -4784,7 +4797,12 @@ def rank(
         -------
         [NAME_REDACTED] ranking of values within each group.
-        %(see_also)s
+
+        See Also
+        --------
+        Series.rank : Apply function rank to a Series.
+        DataFrame.rank : Apply function rank to each row or column of a DataFrame.
+
         Examples
         --------
         >>> df = pd.DataFrame(
@@ -4838,8 +4856,6 @@ def rank(
         )

     [USER_REDACTED]
-    [USER_REDACTED](name="groupby")
-    [USER_REDACTED](see_also=_common_see_also)
     def cumprod(self, numeric_only: bool = False, *args, **kwargs) -> NDFrameT:
         """
         Cumulative product for each group.
@@ -4858,7 +4874,12 @@ def cumprod(self, numeric_only: bool = False, *args, **kwargs) -> NDFrameT:
         -------
         Series or [NAME_REDACTED] product for each group. Same object type as the caller.
-        %(see_also)s
+
+        See Also
+        --------
+        Series.cumprod : Apply function cumprod to a Series.
+        DataFrame.cumprod : Apply function cumprod to each row or column of a DataFrame.
+
         Examples
         --------
         For SeriesGroupBy:
@@ -4899,8 +4920,6 @@ def cumprod(self, numeric_only: bool = False, *args, **kwargs) -> NDFrameT:
         return self._cython_transform("cumprod", numeric_only, **kwargs)

     [USER_REDACTED]
-    [USER_REDACTED](name="groupby")
-    [USER_REDACTED](see_also=_common_see_also)
     def cumsum(self, numeric_only: bool = False, *args, **kwargs) -> NDFrameT:
         """
         Cumulative sum for each group.
@@ -4919,7 +4938,12 @@ def cumsum(self, numeric_only: bool = False, *args, **kwargs) -> NDFrameT:
         -------
         Series or [NAME_REDACTED] sum for each group. Same object type as the caller.
-        %(see_also)s
+
+        See Also
+        --------
+        Series.cumsum : Apply function cumsum to a Series.
+        DataFrame.cumsum : Apply function cumsum to each row or column of a DataFrame.
+
         Examples
         --------
         For SeriesGroupBy:
@@ -4960,8 +4984,6 @@ def cumsum(self, numeric_only: bool = False, *args, **kwargs) -> NDFrameT:
         return self._cython_transform("cumsum", numeric_only, **kwargs)

     [USER_REDACTED]
-    [USER_REDACTED](name="groupby")
-    [USER_REDACTED](see_also=_common_see_also)
     def cummin(
         self,
         numeric_only: bool = False,
@@ -4982,7 +5004,12 @@ def cummin(
         -------
         Series or [NAME_REDACTED] min for each group. Same object type as the caller.
-        %(see_also)s
+
+        See Also
+        --------
+        Series.cummin : Apply function cummin to a Series.
+        DataFrame.cummin : Apply function cummin to each row or column of a DataFrame.
+
         Examples
         --------
         For SeriesGroupBy:
@@ -5031,8 +5058,6 @@ def cummin(
         )

     [USER_REDACTED]
-    [USER_REDACTED](name="groupby")
-    [USER_REDACTED](see_also=_common_see_also)
     def cummax(
         self,
         numeric_only: bool = False,
@@ -5053,7 +5078,12 @@ def cummax(
         -------
         Series or [NAME_REDACTED] max for each group. Same object type as the caller.
-        %(see_also)s
+
+        See Also
+        --------
+        Series.cummax : Apply function cummax to a Series.
+        DataFrame.cummax : Apply function cummax to each row or column of a DataFrame.
+
         Examples
         --------
         For SeriesGroupBy:
@@ -5102,7 +5132,6 @@ def cummax(
         )

     [USER_REDACTED]
-    [USER_REDACTED](name="groupby")
     def shift(
         self,
         periods: int | Sequence[int] = 1,
@@ -5248,8 +5277,6 @@ def shift(
         )

     [USER_REDACTED]
-    [USER_REDACTED](name="groupby")
-    [USER_REDACTED](see_also=_common_see_also)
     def diff(
         self,
         periods: int = 1,
@@ -5269,7 +5296,12 @@ def diff(
         -------
         Series or [NAME_REDACTED] differences.
-        %(see_also)s
+
+        See Also
+        --------
+        Series.diff : Apply function diff to a Series.
+        DataFrame.diff : Apply function diff to each row or column of a DataFrame.
+
         Examples
         --------
         For SeriesGroupBy:
@@ -5335,8 +5367,6 @@ def diff(
         return obj - shifted

     [USER_REDACTED]
-    [USER_REDACTED](name="groupby")
-    [USER_REDACTED](see_also=_common_see_also)
     def pct_change(
         self,
         periods: int = 1,
@@ -5365,7 +5395,13 @@ def pct_change(
         -------
         Series or [NAME_REDACTED] changes within each group.
-        %(see_also)s
+
+        See Also
+        --------
+        Series.pct_change : Apply function pct_change to a Series.
+        DataFrame.pct_change : Apply function pct_change to each row or column of
+            a DataFrame.
+
         Examples
         --------

@@ -5431,8 +5467,6 @@ def pct_change(
         return (filled / shifted) - 1

     [USER_REDACTED]
-    [USER_REDACTED](name="groupby")
-    [USER_REDACTED](see_also=_common_see_also)
     def head(self, n: int = 5) -> NDFrameT:
         """
         Return first n rows of each group.
@@ -5451,7 +5485,12 @@ def head(self, n: int = 5) -> NDFrameT:
         -------
         Series or [NAME_REDACTED] of original Series or DataFrame as determined by n.
-        %(see_also)s
+
+        See Also
+        --------
+        Series.head : Apply function head to a Series.
+        DataFrame.head : Apply function head to each row or column of a DataFrame.
+
         Examples
         --------

@@ -5468,8 +5507,6 @@ def head(self, n: int = 5) -> NDFrameT:
         return self._mask_selected_obj(mask)

     [USER_REDACTED]
-    [USER_REDACTED](name="groupby")
-    [USER_REDACTED](see_also=_common_see_also)
     def tail(self, n: int = 5) -> NDFrameT:
         """
         Return last n rows of each group.
@@ -5488,7 +5525,12 @@ def tail(self, n: int = 5) -> NDFrameT:
         -------
         Series or [NAME_REDACTED] of original Series or DataFrame as determined by n.
-        %(see_also)s
+
+        See Also
+        --------
+        Series.tail : Apply function tail to a Series.
+        DataFrame.tail : Apply function tail to each row or column of a DataFrame.
+
         Examples
         --------

```suggestion
        Series.any : Apply a function any to a Series.
```
This was probably a typo before, but I think these should refer to the method of the same name on the Series/DataFrame object. Can you apply similar fixes to the other methods?

sure, thanks for pointing it out


DOC: Fix SA01,EX01 for pandas.DataFrame.from_arrow

- [x] closes #63540
- [ ] [Tests added and passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#writing-tests) if fixing a bug or adding a new feature
- [ ] All [code checks passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#pre-commit).
- [ ] Added [type annotations](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#type-hints) to new arguments/methods/functions.
- [ ] Added an entry in the latest `doc/source/whatsnew/vX.X.X.rst` file if fixing a bug or adding a new feature.
- [ ] If I used AI to develop this pull request, I prompted it to follow `AGENTS.md`.

@@ -70,7 +70,6 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then
     "$BASE_DIR"/scripts/validate_docstrings.py \
         --format=actions \
         -i ES01 `# For now it is ok if docstrings are missing the extended summary` \
-        -i "pandas.DataFrame.from_arrow SA01,EX01" \
         -i "pandas.Series.from_arrow SA01,EX01" \
         -i "pandas.Series.dt PR01" `# Accessors are implemented as classes, but we do not document the Parameters section` \
         -i "pandas.Period.freq GL08" \

@@ -1864,6 +1864,20 @@ def from_arrow(
         Returns
         -------
         DataFrame
+
+        See Also
+        --------
+        Series.from_arrow : Construct a Series from an Arrow object.
+
+        Examples
+        --------
+        >>> import pyarrow as pa
+        >>> table = pa.table({"a": [1, 2, 3], "b": ["x", "y", "z"]})
+        >>> pd.DataFrame.from_arrow(table)
+           a  b
+        0  1  x
+        1  2  y
+        2  3  z
         """
         pa = import_optional_dependency("pyarrow", min_version="14.0.0")
         if not isinstance(data, pa.Table):

pyarrow should be installed in our doc environment, so could you remove these doctest skips?

yes let me do that.


DOC: Fix PR02 docstring validation errors for groupby.plot

- Remove `[USER_REDACTED]()` decorator from SeriesGroupBy.plot and DataFrameGroupBy.plot
- Add explicit docstrings with Returns and See Also sections
- Remove PR02 ignore entries from code_checks.sh

```
-i "pandas.api.typing.DataFrameGroupBy.plot PR02" \
-i "pandas.api.typing.SeriesGroupBy.plot PR02" \
```

Part of #60365

- [ ] closes #xxxx (Replace xxxx with the GitHub issue number)
- [ ] [Tests added and passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#writing-tests) if fixing a bug or adding a new feature
- [x] All [code checks passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#pre-commit).
- [ ] Added [type annotations](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#type-hints) to new arguments/methods/functions.
- [ ] Added an entry in the latest `doc/source/whatsnew/vX.X.X.rst` file if fixing a bug or adding a new feature.
- [ ] If I used AI to develop this pull request, I prompted it to follow `AGENTS.md`.

@@ -78,8 +78,6 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then
         -i "pandas.errors.ChainedAssignmentError SA01" \
         -i "pandas.errors.IncompatibleFrequency SA01,SS06,EX01" \
         -i "pandas.api.extensions.ExtensionArray.value_counts EX01,RT03,SA01" \
-        -i "pandas.api.typing.DataFrameGroupBy.plot PR02" \
-        -i "pandas.api.typing.SeriesGroupBy.plot PR02" \
         -i "pandas.api.typing.Resampler.quantile PR01,PR07" \
         -i "pandas.StringDtype.storage SA01" \
         -i "pandas.StringDtype.na_value SA01" \

@@ -1514,8 +1514,28 @@ def alt(obj):
         )

     [USER_REDACTED]
-    [USER_REDACTED](Series.plot.__doc__)
     def plot(self) -> GroupByPlot:
+        """
+        Make plots of groups from a Series.
+
+        Uses the backend specified by [NAME_REDACTED] ``plotting.backend``.
+        By default, matplotlib is used.
+
+        Returns
+        -------
+        GroupByPlot
+            A plotting object that can be used to create plots for each group.
+
+        See Also
+        --------
+        Series.plot : Make plots of Series.
+
+        Examples
+        --------
+        >>> ser = pd.Series([1, 2, 3, 4, 5], index=["a", "a", "b", "b", "c"])
+        >>> g = ser.groupby(level=0)
+        >>> g.plot()  # doctest: +SKIP
+        """
         result = GroupByPlot(self)
         return result

@@ -3528,8 +3548,30 @@ def kurt(
         )

     [USER_REDACTED]
-    [USER_REDACTED](DataFrame.plot.__doc__)
     def plot(self) -> GroupByPlot:
+        """
+        Make plots of groups from a DataFrame.
+
+        Uses the backend specified by [NAME_REDACTED] ``plotting.backend``.
+        By default, matplotlib is used.
+
+        Returns
+        -------
+        GroupByPlot
+            A plotting object that can be used to create plots for each group.
+
+        See Also
+        --------
+        DataFrame.plot : Make plots of DataFrame.
+
+        Examples
+        --------
+        >>> df = pd.DataFrame(
+        ...     {"A": [1, 2, 3, 4], "B": [5, 6, 7, 8]}, index=["a", "a", "b", "b"]
+        ... )
+        >>> g = df.groupby(level=0)
+        >>> g.plot()  # doctest: +SKIP
+        """
         result = GroupByPlot(self)
         return result

Looks good! I think we can might the first line just a bit more descriptive.

lgtm

```suggestion
        Make plots of groups from a Series.
```

```suggestion
        Make plots of groups from a DataFrame.
```

Thanks for the review! I've applied your suggestions.


DOC: Inline docstring in `pandas/io/json/_json.py`

- [ ] xref #62437 (Replace xxxx with the GitHub issue number)
- [ ] [Tests added and passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#writing-tests) if fixing a bug or adding a new feature
- [x] All [code checks passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#pre-commit).
- [ ] Added [type annotations](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#type-hints) to new arguments/methods/functions.
- [ ] Added an entry in the latest `doc/source/whatsnew/vX.X.X.rst` file if fixing a bug or adding a new feature.
- [ ] If I used AI to develop this pull request, I prompted it to follow `AGENTS.md`.

@@ -29,10 +29,7 @@
 from pandas._libs.tslibs import iNaT
 from pandas.compat._optional import import_optional_dependency
 from pandas.errors import AbstractMethodError
-from pandas.util._decorators import (
-    doc,
-    set_module,
-)
+from pandas.util._decorators import set_module
 from pandas.util._validators import check_dtype_backend

 from pandas.core.dtypes.common import (
@@ -53,7 +50,6 @@
     to_datetime,
 )
 from pandas.core.reshape.concat import concat
-from pandas.core.shared_docs import _shared_docs

 from pandas.io._util import arrow_table_to_pandas
 from pandas.io.common import (
@@ -500,10 +496,6 @@ def read_json(

 [USER_REDACTED]_module("pandas")
-[USER_REDACTED](
-    storage_options=_shared_docs["storage_options"],
-    decompression_options=_shared_docs["decompression_options"] % "path_or_buf",
-)
 def read_json(
     path_or_buf: FilePath | ReadBuffer[str] | ReadBuffer[bytes],
     *,
@@ -648,14 +640,39 @@ def read_json(
         for more information on ``chunksize``.
         This can only be passed if `lines=True`.
         If this is None, the file will be read into memory all at once.
-    {decompression_options}
+
+    compression : str or dict, default 'infer'
+        For on-the-fly decompression of on-disk data. If 'infer' and 'path_or_buf' is
+        path-like, then detect compression from the following extensions: '.gz',
+        '.bz2', '.zip', '.xz', '.zst', '.tar', '.tar.gz', '.tar.xz' or '.tar.bz2'
+        (otherwise no compression).
+        If using 'zip' or 'tar', the ZIP file must contain only one data file to be
+        read in.
+        Set to ``None`` for no decompression.
+        Can also be a dict with key ``'method'`` set
+        to one of {``'zip'``, ``'gzip'``, ``'bz2'``, ``'zstd'``, ``'xz'``, ``'tar'``}
+        and other key-value pairs are forwarded to
+        ``zipfile.ZipFile``, ``gzip.GzipFile``,
+        ``bz2.BZ2File``, ``zstandard.ZstdDecompressor``, ``lzma.LZMAFile`` or
+        ``tarfile.TarFile``, respectively.
+        As an example, the following could be passed for Zstandard decompression using a
+        custom compression dictionary:
+        ``compression={'method': 'zstd', 'dict_data': my_compression_dict}``.

     nrows : int, optional
         The number of lines from the line-delimited jsonfile that has to be read.
         This can only be passed if `lines=True`.
         If this is None, all the rows will be returned.

-    {storage_options}
+    storage_options : dict, optional
+        Extra options that make sense for a particular storage connection, e.g.
+        host, port, username, password, etc. For HTTP(S) URLs the key-value pairs
+        are forwarded to ``urllib.request.Request`` as header options. For other
+        URLs (e.g. starting with "s3://", and "gcs://") the key-value pairs are
+        forwarded to ``fsspec.open``. Please see ``fsspec`` and ``urllib`` for more
+        details, and for more examples on storage options refer `here
+        <https://pandas.pydata.org/docs/user_guide/io.html?
+        highlight=storage_options#reading-writing-remote-files>`_.

     dtype_backend : {{'numpy_nullable', 'pyarrow'}}
         Back-end data type applied to the resultant :class:`DataFrame`
@@ -701,74 +718,61 @@ def read_json(
     Examples
     --------
     >>> from io import StringIO
-    >>> df = pd.DataFrame([['a', 'b'], ['c', 'd']],
-    ...                   index=['row 1', 'row 2'],
-    ...                   columns=['col 1', 'col 2'])
+    >>> df = pd.DataFrame(
+    ...     [["a", "b"], ["c", "d"]],
+    ...     index=["row 1", "row 2"],
+    ...     columns=["col 1", "col 2"],
+    ... )

     Encoding/decoding a Dataframe using ``'split'`` formatted JSON:

-    >>> df.to_json(orient='split')
-        '\
-{{\
-"columns":["col 1","col 2"],\
-"index":["row 1","row 2"],\
-"data":[["a","b"],["c","d"]]\
-}}\
-'
-    >>> pd.read_json(StringIO(_), orient='split')  # noqa: F821
+    >>> df.to_json(orient="split")
+    '{"columns":["col 1","col 2"],"index":["row 1","row 2"],"data":[["a","b"],["c","d"]]}'
+
+    >>> pd.read_json(StringIO(_), orient="split")  # noqa: F821
           col 1 col 2
     row 1     a     b
     row 2     c     d

     Encoding/decoding a Dataframe using ``'index'`` formatted JSON:

-    >>> df.to_json(orient='index')
-    '{{"row 1":{{"col 1":"a","col 2":"b"}},"row 2":{{"col 1":"c","col 2":"d"}}}}'
+    >>> df.to_json(orient="index")
+    '{"row 1":{"col 1":"a","col 2":"b"},"row 2":{"col 1":"c","col 2":"d"}}'

-    >>> pd.read_json(StringIO(_), orient='index')  # noqa: F821
+    >>> pd.read_json(StringIO(_), orient="index")  # noqa: F821
           col 1 col 2
     row 1     a     b
     row 2     c     d

     Encoding/decoding a Dataframe using ``'records'`` formatted JSON.
     Note that index labels are not preserved with this encoding.

-    >>> df.to_json(orient='records')
-    '[{{"col 1":"a","col 2":"b"}},{{"col 1":"c","col 2":"d"}}]'
-    >>> pd.read_json(StringIO(_), orient='records')  # noqa: F821
+    >>> df.to_json(orient="records")
+    '[{"col 1":"a","col 2":"b"},{"col 1":"c","col 2":"d"}]'
+
+    >>> pd.read_json(StringIO(_), orient="records")  # noqa: F821
       col 1 col 2
     0     a     b
     1     c     d

     Encoding with [NAME_REDACTED]

-    >>> df.to_json(orient='table')
-        '\
-{{"schema":{{"fields":[\
-{{"name":"index","type":"string","extDtype":"str"}},\
-{{"name":"col 1","type":"string","extDtype":"str"}},\
-{{"name":"col 2","type":"string","extDtype":"str"}}],\
-"primaryKey":["index"],\
-"pandas_version":"1.4.0"}},\
-"data":[\
-{{"index":"row 1","col 1":"a","col 2":"b"}},\
-{{"index":"row 2","col 1":"c","col 2":"d"}}]\
-}}\
-'
+    >>> df.to_json(orient="table")
+    '{"schema":{"fields":[{"name":"index","type":"string","extDtype":"str"},{"name":"col 1","type":"string","extDtype":"str"},{"name":"col 2","type":"string","extDtype":"str"}],"primaryKey":["index"],"pandas_version":"1.4.0"},"data":[{"index":"row 1","col 1":"a","col 2":"b"},{"index":"row 2","col 1":"c","col 2":"d"}]}'

     The following example uses ``dtype_backend="numpy_nullable"``

-    >>> data = '''{{"index": {{"0": 0, "1": 1}},
-    ...        "a": {{"0": 1, "1": null}},
-    ...        "b": {{"0": 2.5, "1": 4.5}},
-    ...        "c": {{"0": true, "1": false}},
-    ...        "d": {{"0": "a", "1": "b"}},
-    ...        "e": {{"0": 1577.2, "1": 1577.1}}}}'''
+    >>> data = '''{"index": {"0": 0, "1": 1},
+    ...        "a": {"0": 1, "1": null},
+    ...        "b": {"0": 2.5, "1": 4.5},
+    ...        "c": {"0": true, "1": false},
+    ...        "d": {"0": "a", "1": "b"},
+    ...        "e": {"0": 1577.2, "1": 1577.1}}'''
     >>> pd.read_json(StringIO(data), dtype_backend="numpy_nullable")
        index     a    b      c  d       e
     0      0     1  2.5   True  a  1577.2
     1      1  <NA>  4.5  False  b  1577.1
-    """
+    """  # noqa: E501
     if orient == "table" and dtype:
         raise ValueError("cannot pass both dtype and orient='table'")
     if orient == "table" and convert_axes:

```suggestion
```


DOC: Inline docstring in `pandas/io/common.py`

@@ -56,7 +56,6 @@
     ReadCsvBuffer,
 )
 from pandas.compat._optional import import_optional_dependency
-from pandas.util._decorators import doc
 from pandas.util._exceptions import find_stack_level

 from pandas.core.dtypes.common import (
@@ -67,8 +66,6 @@
 )
 from pandas.core.dtypes.generic import ABCMultiIndex

-from pandas.core.shared_docs import _shared_docs
-
 _VALID_URLS = set(uses_relative + uses_netloc + uses_params)
 _VALID_URLS.discard("")
 _FSSPEC_URL_PATTERN = re.compile(r"^[A-Za-z][A-Za-z0-9+\-+.]*(::[A-Za-z0-9+\-+.]+)*://")
@@ -296,10 +293,6 @@ def is_fsspec_url(url: FilePath | BaseBuffer) -> bool:
     )

-[USER_REDACTED](
-    storage_options=_shared_docs["storage_options"],
-    compression_options=_shared_docs["compression_options"] % "filepath_or_buffer",
-)
 def _get_filepath_or_buffer(
     filepath_or_buffer: FilePath | BaseBuffer,
     encoding: str = "utf-8",
@@ -315,12 +308,36 @@ def _get_filepath_or_buffer(
     ----------
     filepath_or_buffer : a url, filepath (str or pathlib.Path),
                          or buffer
-    {compression_options}
+
+    compression : str or dict, default 'infer'
+        For on-the-fly compression of the output data. If 'infer' and
+        'filepath_or_buffer' is path-like, then detect compression from the
+        following extensions: '.gz',
+        '.bz2', '.zip', '.xz', '.zst', '.tar', '.tar.gz', '.tar.xz' or '.tar.bz2'
+        (otherwise no compression).
+        Set to ``None`` for no compression.
+        Can also be a dict with key ``'method'`` set
+        to one of {``'zip'``, ``'gzip'``, ``'bz2'``, ``'zstd'``, ``'xz'``, ``'tar'``}
+        and other key-value pairs are forwarded to
+        ``zipfile.ZipFile``, ``gzip.GzipFile``,
+        ``bz2.BZ2File``, ``zstandard.ZstdCompressor``, ``lzma.LZMAFile`` or
+        ``tarfile.TarFile``, respectively.
+        As an example, the following could be passed for faster compression and to
+        create a reproducible gzip archive:
+        ``compression={'method': 'gzip', 'compresslevel': 1, 'mtime': 1}``.

     encoding : the encoding to use to decode bytes, default is 'utf-8'
     mode : str, optional

-    {storage_options}
+    storage_options : dict, optional
+        Extra options that make sense for a particular storage connection, e.g.
+        host, port, username, password, etc. For HTTP(S) URLs the key-value pairs
+        are forwarded to ``urllib.request.Request`` as header options. For other
+        URLs (e.g. starting with "s3://", and "gcs://") the key-value pairs are
+        forwarded to ``fsspec.open``. Please see ``fsspec`` and ``urllib`` for more
+        details, and for more examples on storage options refer `here
+        <https://pandas.pydata.org/docs/user_guide/io.html?
+        highlight=storage_options#reading-writing-remote-files>`_.

     Returns the dataclass IOArgs.
@@ -550,7 +567,6 @@ def get_compression_method(
     return compression_method, compression_args

-[USER_REDACTED](compression_options=_shared_docs["compression_options"] % "filepath_or_buffer")
 def infer_compression(
     filepath_or_buffer: FilePath | BaseBuffer, compression: str | None
 ) -> str | None:
@@ -564,7 +580,23 @@ def infer_compression(
     ----------
     filepath_or_buffer : str or file handle
         File path or object.
-    {compression_options}
+
+    compression : str or dict, default 'infer'
+        For on-the-fly compression of the output data. If 'infer' and
+        'filepath_or_buffer' is path-like, then detect compression from the
+        following extensions: '.gz',
+        '.bz2', '.zip', '.xz', '.zst', '.tar', '.tar.gz', '.tar.xz' or '.tar.bz2'
+        (otherwise no compression).
+        Set to ``None`` for no compression.
+        Can also be a dict with key ``'method'`` set
+        to one of {``'zip'``, ``'gzip'``, ``'bz2'``, ``'zstd'``, ``'xz'``, ``'tar'``}
+        and other key-value pairs are forwarded to
+        ``zipfile.ZipFile``, ``gzip.GzipFile``,
+        ``bz2.BZ2File``, ``zstandard.ZstdCompressor``, ``lzma.LZMAFile`` or
+        ``tarfile.TarFile``, respectively.
+        As an example, the following could be passed for faster compression and to
+        create a reproducible gzip archive:
+        ``compression={'method': 'gzip', 'compresslevel': 1, 'mtime': 1}``.

     Returns
     -------
@@ -662,7 +694,6 @@ def get_handle(
 ) -> IOHandles[str] | IOHandles[bytes]: ...

-[USER_REDACTED](compression_options=_shared_docs["compression_options"] % "path_or_buf")
 def get_handle(
     path_or_buf: FilePath | BaseBuffer,
     mode: str,
@@ -685,7 +716,21 @@ def get_handle(
         Mode to open path_or_buf with.
     encoding : str or None
         Encoding to use.
-    {compression_options}
+    compression : str or dict, default 'infer'
+        For on-the-fly compression of the output data. If 'infer' and 'path_or_buf'
+        is path-like, then detect compression from the following extensions: '.gz',
+        '.bz2', '.zip', '.xz', '.zst', '.tar', '.tar.gz', '.tar.xz' or '.tar.bz2'
+        (otherwise no compression).
+        Set to ``None`` for no compression.
+        Can also be a dict with key ``'method'`` set
+        to one of {``'zip'``, ``'gzip'``, ``'bz2'``, ``'zstd'``, ``'xz'``, ``'tar'``}
+        and other key-value pairs are forwarded to
+        ``zipfile.ZipFile``, ``gzip.GzipFile``,
+        ``bz2.BZ2File``, ``zstandard.ZstdCompressor``, ``lzma.LZMAFile`` or
+        ``tarfile.TarFile``, respectively.
+        As an example, the following could be passed for faster compression and to
+        create a reproducible gzip archive:
+        ``compression={'method': 'gzip', 'compresslevel': 1, 'mtime': 1}``.

            May be a dict with key 'method' as compression mode
            and other keys as compression options if compression

```suggestion
```

```suggestion
```

```suggestion
```


DOC: Inline docstring in `pandas/io/formats/xml.py`

@@ -13,16 +13,11 @@
 )

 from pandas.errors import AbstractMethodError
-from pandas.util._decorators import (
-    cache_readonly,
-    doc,
-)
+from pandas.util._decorators import cache_readonly

 from pandas.core.dtypes.common import is_list_like
 from pandas.core.dtypes.missing import isna

-from pandas.core.shared_docs import _shared_docs
-
 from pandas.io.common import get_handle
 from pandas.io.xml import get_data_from_filepath

@@ -38,10 +33,6 @@
     from pandas import DataFrame

-[USER_REDACTED](
-    storage_options=_shared_docs["storage_options"],
-    compression_options=_shared_docs["compression_options"] % "path_or_buffer",
-)
 class _BaseXMLFormatter:
     """
     Subclass for formatting data in XML.
@@ -89,9 +80,31 @@ class _BaseXMLFormatter:
     stylesheet : str or file-like
         A URL, file, file-like object, or a raw string containing XSLT.

-    {compression_options}
-
-    {storage_options}
+    compression : str or dict, default 'infer'
+        For on-the-fly compression of the output data. If 'infer' and 'path_or_buffer'
+        is path-like, then detect compression from the following extensions: '.gz',
+        '.bz2', '.zip', '.xz', '.zst', '.tar', '.tar.gz', '.tar.xz' or '.tar.bz2'
+        (otherwise no compression).
+        Set to ``None`` for no compression.
+        Can also be a dict with key ``'method'`` set
+        to one of {``'zip'``, ``'gzip'``, ``'bz2'``, ``'zstd'``, ``'xz'``, ``'tar'``}
+        and other key-value pairs are forwarded to
+        ``zipfile.ZipFile``, ``gzip.GzipFile``,
+        ``bz2.BZ2File``, ``zstandard.ZstdCompressor``, ``lzma.LZMAFile`` or
+        ``tarfile.TarFile``, respectively.
+        As an example, the following could be passed for faster compression and to
+        create a reproducible gzip archive:
+        ``compression={'method': 'gzip', 'compresslevel': 1, 'mtime': 1}``.
+
+    storage_options : dict, optional
+        Extra options that make sense for a particular storage connection, e.g.
+        host, port, username, password, etc. For HTTP(S) URLs the key-value pairs
+        are forwarded to ``urllib.request.Request`` as header options. For other
+        URLs (e.g. starting with "s3://", and "gcs://") the key-value pairs are
+        forwarded to ``fsspec.open``. Please see ``fsspec`` and ``urllib`` for more
+        details, and for more examples on storage options refer `here
+        <https://pandas.pydata.org/docs/user_guide/io.html?
+        highlight=storage_options#reading-writing-remote-files>`_.

     See also
     --------

```suggestion
```


DOC: Inline docstrings for argmax and argmin in base.py

- Replaced dynamic [USER_REDACTED] decorators with hardcoded docstrings in pandas/core/base.py
- Targeted methods: argmax, argmin
- Fixes whitespace/formatting in examples to satisfy doctests
- Part of #62437

- [x] xref #62437 (Replace xxxx with the GitHub issue number)
- [x] [Tests added and passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#writing-tests) if fixing a bug or adding a new feature
- [x] All [code checks passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#pre-commit).
- [ ] Added [type annotations](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#type-hints) to new arguments/methods/functions.
- [ ] Added an entry in the latest `doc/source/whatsnew/vX.X.X.rst` file if fixing a bug or adding a new feature.
- [x] If I used AI to develop this pull request, I prompted it to follow `AGENTS.md`.

@@ -749,19 +749,18 @@ def empty(self) -> bool:
         """
         return not self.size

-    [USER_REDACTED](op="max", oppose="min", value="largest")
     def argmax(
         self, axis: AxisInt | None = None, skipna: bool = True, *args, **kwargs
     ) -> int:
         """
-        Return int position of the {value} value in the Series.
+        Return int position of the largest value in the Series.

-        If the {op}imum is achieved in multiple locations,
+        If the maximum is achieved in multiple locations,
         the first row position is returned.

         Parameters
         ----------
-        axis : {{None}}
+        axis : None
             Unused. Parameter needed for compatibility with DataFrame.
         skipna : bool, default True
             Exclude NA/null values. If the entire Series is NA, or if ``skipna=False``
@@ -772,13 +771,13 @@ def argmax(
         Returns
         -------
         int
-            Row position of the {op}imum value.
+            Row position of the maximum value.

         See Also
         --------
-        Series.arg{op} : Return position of the {op}imum value.
-        Series.arg{oppose} : Return position of the {oppose}imum value.
-        numpy.ndarray.arg{op} : Equivalent method for numpy arrays.
+        Series.argmax : Return position of the maximum value.
+        Series.argmin : Return position of the minimum value.
+        numpy.ndarray.argmax : Equivalent method for numpy arrays.
         Series.idxmax : Return index label of the maximum values.
         Series.idxmin : Return index label of the minimum values.

@@ -823,10 +822,67 @@ def argmax(
             # "int")
             return result  # type: ignore[return-value]

-    [USER_REDACTED](argmax, op="min", oppose="max", value="smallest")
     def argmin(
         self, axis: AxisInt | None = None, skipna: bool = True, *args, **kwargs
     ) -> int:
+        """
+        Return int position of the smallest value in the Series.
+
+        If the minimum is achieved in multiple locations,
+        the first row position is returned.
+
+        Parameters
+        ----------
+        axis : None
+            Unused. Parameter needed for compatibility with DataFrame.
+        skipna : bool, default True
+            Exclude NA/null values. If the entire Series is NA, or if ``skipna=False``
+            and there is an NA value, this method will raise a ``ValueError``.
+        *args, **kwargs
+            Additional arguments and keywords for compatibility with NumPy.
+
+        Returns
+        -------
+        int
+            Row position of the minimum value.
+
+        See Also
+        --------
+        Series.argmin : Return position of the minimum value.
+        Series.argmax : Return position of the maximum value.
+        numpy.ndarray.argmin : Equivalent method for numpy arrays.
+        Series.idxmin : Return index label of the minimum values.
+        Series.idxmax : Return index label of the maximum values.
+
+        Examples
+        --------
+        Consider dataset containing cereal calories
+
+        >>> s = pd.Series(
+        ...     [100.0, 110.0, 120.0, 110.0],
+        ...     index=[
+        ...         "[NAME_REDACTED]",
+        ...         "[NAME_REDACTED]",
+        ...         "[NAME_REDACTED]",
+        ...         "[NAME_REDACTED]",
+        ...     ],
+        ... )
+        >>> s
+        [NAME_REDACTED]              100.0
+        [NAME_REDACTED]           110.0
+        [NAME_REDACTED]    120.0
+        [NAME_REDACTED]               110.0
+        dtype: float64
+
+        >>> s.argmax()
+        np.int64(2)
+        >>> s.argmin()
+        np.int64(0)
+
+        The maximum cereal calories is the third element and
+        the minimum cereal calories is the first element,
+        since series is zero-indexed.
+        """
         delegate = self._values
         nv.validate_minmax_axis(axis)
         skipna = nv.validate_argmax_with_skipna(skipna, args, kwargs)

Can you avoid the doctest skips with your chages?

```suggestion
        axis : None
```

```suggestion
        axis : None
```

Removed the brackets.

Fixed! fixed the doctrings to pass the doctests and removed skips.


BUG: pd.Grouper does not retain PyArrow index dtype

- [x] closes #63518 (Replace xxxx with the GitHub issue number)
- [ ] [Tests added and passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#writing-tests) if fixing a bug or adding a new feature
- [ ] All [code checks passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#pre-commit).
- [ ] Added [type annotations](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#type-hints) to new arguments/methods/functions.
- [ ] Added an entry in the latest `doc/source/whatsnew/vX.X.X.rst` file if fixing a bug or adding a new feature.
- [ ] If I used AI to develop this pull request, I prompted it to follow `AGENTS.md`.

@@ -1358,6 +1358,7 @@ Groupby/resample/rolling
 - Bug in :meth:`.Rolling.var` and :meth:`.Rolling.std` computing incorrect results due to numerical instability. (:issue:`47721`, :issue:`52407`, :issue:`54518`, :issue:`55343`)
 - Bug in :meth:`DataFrame.groupby` methods when operating on NumPy-nullable data failing when the NA mask was not C-contiguous (:issue:`61031`)
 - Bug in :meth:`DataFrame.groupby` when grouping by a Series and that Series was modified after calling :meth:`DataFrame.groupby` but prior to the groupby operation (:issue:`63219`)
+- Bug in :meth:`DataFrame.groupby` with a :class:`TimeGrouper` (e.g. ``pd.Grouper(freq="D")``) not retaining PyArrow index dtype (:issue:`63518`)

 Reshaping
 ^^^^^^^^^

@@ -242,6 +242,8 @@ def _get_binner(self):
         """
         binner, bins, binlabels = self._get_binner_for_time()
         assert len(bins) == len(binlabels)
+        if self._timegrouper._arrow_dtype is not None:
+            binlabels = binlabels.astype(self._timegrouper._arrow_dtype)
         bin_grouper = BinGrouper(bins, binlabels, indexer=self._indexer)
         return binner, bin_grouper

@@ -11,6 +11,8 @@
 import numpy as np
 import pytest

+import pandas.util._test_decorators as td
+
 import pandas as pd
 from pandas import (
     DataFrame,
@@ -956,3 +958,27 @@ def test_groupby_agg_numba_timegrouper_with_nat(
         )
         expected_df = gb[["Quantity"]].aggregate("mean")
         tm.assert_frame_equal(result_df, expected_df)
+
+    [USER_REDACTED].skip_if_no("pyarrow")
+    def test_pyarrow_index_retention(self):
+        # https://github.com/[USER_REDACTED]ndas-dev/pandas/issues/63518
+        df = DataFrame(
+            {
+                "a": [1, 2, 3],
+            },
+            index=Index(
+                [
+                    Timestamp("2013-01-01"),
+                    Timestamp("2013-01-01"),
+                    Timestamp("2013-01-02"),
+                ],
+                dtype="timestamp[ns, America/Denver][pyarrow]",
+            ),
+        )
+        gb = df.groupby(Grouper(freq="D"))
+        result = gb._grouper.result_index
+        expected = Index(
+            [Timestamp("2013-01-01"), Timestamp("2013-01-02")],
+            dtype="timestamp[ns, America/Denver][pyarrow]",
+        )
+        tm.assert_index_equal(result, expected)

is there a reason why we have to do a cast-back approach instead of prevent-casting-away earlier on?

It's not exactly a cast-back, the labels are generated directly via `date_range`.

https://github.com/[USER_REDACTED]ndas-dev/pandas/blob/adf237214db1600e271fc5ff87b2a419f991a830/pandas/core/resample.py#L2590-L2599

We'd need to generate these as arrow-backed data. More generally, to avoid casting the index to a DatetimeIndex, we'd need a replacement for `generate_bins_dt64` which relies on NumPy data.

Thanks for explaining.  No objections here.


DOC: Inline docstring in `pandas/io/formats/style.py`

- [x] closes #62437 (Replace xxxx with the GitHub issue number)
- [ ] [Tests added and passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#writing-tests) if fixing a bug or adding a new feature
- [x] All [code checks passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#pre-commit).
- [ ] Added [type annotations](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#type-hints) to new arguments/methods/functions.
- [ ] Added an entry in the latest `doc/source/whatsnew/vX.X.X.rst` file if fixing a bug or adding a new feature.
- [ ] If I used AI to develop this pull request, I prompted it to follow `AGENTS.md`.

@@ -7,7 +7,6 @@
 import copy
 from functools import partial
 import operator
-import textwrap
 from typing import (
     TYPE_CHECKING,
     Concatenate,
@@ -20,10 +19,6 @@
 from pandas._config import get_option

 from pandas.compat._optional import import_optional_dependency
-from pandas.util._decorators import (
-    Substitution,
-    doc,
-)

 import pandas as pd
 from pandas import (
@@ -35,8 +30,6 @@
     DataFrame,
     Series,
 )
-from pandas.core.generic import NDFrame
-from pandas.core.shared_docs import _shared_docs

 from pandas.io.formats.format import save_to_buffer

@@ -83,34 +76,7 @@
     )

     from pandas import ExcelWriter
-
-
-####
-# [NAME_REDACTED]
-
-subset_args = """subset : label, array-like, IndexSlice, optional
-            A valid 2d input to `DataFrame.loc[<subset>]`, or, in the case of a 1d input
-            or single key, to `DataFrame.loc[:, <subset>]` where the columns are
-            prioritised, to limit ``data`` to *before* applying the function."""
-
-properties_args = """props : str, default None
-           CSS properties to use for highlighting. If ``props`` is given, ``color``
-           is not used."""
-
-coloring_args = """color : str, default '{default}'
-           Background color to use for highlighting."""
-
-buffering_args = """buf : str, path object, file-like object, optional
-         String, path object (implementing ``os.PathLike[str]``), or file-like
-         object implementing a string ``write()`` function. If ``None``, the result is
-         returned as a string."""
-
-encoding_args = """encoding : str, optional
-              Character encoding setting for file output (and meta tags if available).
-              Defaults to ``pandas.options.styler.render.encoding`` value of "utf-8"."""
-
-#
-###
+    from pandas.core.generic import NDFrame

 class Styler(StylerRenderer):
@@ -541,25 +507,6 @@ def set_tooltips(

         return self

-    [USER_REDACTED](
-        NDFrame.to_excel,
-        klass="Styler",
-        storage_options=_shared_docs["storage_options"],
-        storage_options_versionadded="1.5.0",
-        encoding_parameter=textwrap.dedent(
-            """\
-        encoding : str or None, default None
-            Unused parameter, present for compatibility.
-        """
-        ),
-        verbose_parameter=textwrap.dedent(
-            """\
-        verbose : str, default True
-            Optional unused parameter, present for compatibility.
-        """
-        ),
-        extra_parameters="",
-    )
     def to_excel(
         self,
         excel_writer: FilePath | WriteExcelBuffer | ExcelWriter,
@@ -581,6 +528,130 @@ def to_excel(
         storage_options: StorageOptions | None = None,
         autofilter: bool = False,
     ) -> None:
+        """
+        [NAME_REDACTED] to an Excel sheet.
+
+        To write a single Styler to an Excel .xlsx file it is only necessary to
+        specify a target file name. To write to multiple sheets it is necessary to
+        create an `ExcelWriter` object with a target file name, and specify a sheet
+        in the file to write to.
+
+        Multiple sheets may be written to by [NAME_REDACTED] `sheet_name`.
+        With all data written to the file it is necessary to save the changes.
+        Note that creating an `ExcelWriter` object with a file name that already exists
+        will overwrite the existing file because the default mode is write.
+
+        Parameters
+        ----------
+        excel_writer : path-like, file-like, or ExcelWriter object
+            File path or existing ExcelWriter.
+        sheet_name : str, default 'Sheet1'
+            Name of sheet which will contain DataFrame.
+        na_rep : str, default ''
+            Missing data representation.
+        float_format : str, optional
+            Format string for floating point numbers. For example
+            ``float_format="%.2f"`` will format 0.1234 to 0.12.
+        columns : sequence or list of str, optional
+            Columns to write.
+        header : bool or list of str, default True
+            Write out the column names. If a list of string is given it is
+            assumed to be aliases for the column names.
+        index : bool, default True
+            Write row names (index).
+        index_label : str or sequence, optional
+            Column label for index column(s) if desired. If not specified, and
+            `header` and `index` are True, then the index names are used. A
+            sequence should be given if the DataFrame uses MultiIndex.
+        startrow : int, default 0
+            Upper left cell row to dump data frame.
+        startcol : int, default 0
+            Upper left cell column to dump data frame.
+        engine : str, optional
+            Write engine to use, 'openpyxl' or 'xlsxwriter'. You can also set this
+            via the options ``io.excel.xlsx.writer`` or
+            ``io.excel.xlsm.writer``.
+        merge_cells : bool or 'columns', default False
+            If True, write MultiIndex index and columns as merged cells.
+            If 'columns', merge MultiIndex column cells only.
+        encoding : str or None, default None
+            Unused parameter, present for compatibility.
+        inf_rep : str, default 'inf'
+            Representation for infinity (there is no native representation for
+            infinity in Excel).
+        verbose : str, default True
+            Optional unused parameter, present for compatibility.
+        freeze_panes : tuple of int (length 2), optional
+            Specifies the one-based bottommost row and rightmost column that
+            is to be frozen.
+        storage_options : dict, optional
+            Extra options that make sense for a particular storage connection, e.g.
+            host, port, username, password, etc. For HTTP(S) URLs the key-value pairs
+            are forwarded to ``urllib.request.Request`` as header options. For other
+            URLs (e.g. starting with "s3://", and "gcs://") the key-value pairs are
+            forwarded to ``fsspec.open``. Please see ``fsspec`` and ``urllib`` for more
+            details, and for more examples on storage options refer `here
+            <https://pandas.pydata.org/docs/user_guide/io.html?
+            highlight=storage_options#reading-writing-remote-files>`_.
+
+        autofilter : bool, default False
+            If True, add automatic filters to all columns.
+
+        See Also
+        --------
+        to_csv : [NAME_REDACTED] to a comma-separated values (csv) file.
+        ExcelWriter : Class for writing DataFrame objects into excel sheets.
+        read_excel : Read an Excel file into a pandas DataFrame.
+        read_csv : Read a comma-separated values (csv) file into DataFrame.
+        io.formats.style.Styler.to_excel : Add styles to Excel sheet.
+
+        Notes
+        -----
+        For compatibility with :meth:`~DataFrame.to_csv`,
+        to_excel serializes lists and dicts to strings before writing.
+
+        Once a workbook has been saved it is not possible to write further
+        data without rewriting the whole workbook.
+
+        pandas will check the number of rows, columns,
+        and cell character count does not exceed Excel's limitations.
+        All other limitations must be checked by [NAME_REDACTED]
+
+        Examples
+        --------
+
+        Create, write to and save a workbook:
+
+        >>> df1 = pd.DataFrame(
+        ...     [["a", "b"], ["c", "d"]],
+        ...     index=["row 1", "row 2"],
+        ...     columns=["col 1", "col 2"],
+        ... )
+        >>> df1.to_excel("output.xlsx")  # doctest: +SKIP
+
+        To specify the sheet name:
+
+        >>> df1.to_excel("output.xlsx", sheet_name="Sheet_name_1")  # doctest: +SKIP
+
+        If you wish to write to more than one sheet in the workbook, it is
+        necessary to specify an ExcelWriter object:
+
+        >>> df2 = df1.copy()
+        >>> with pd.ExcelWriter("output.xlsx") as writer:  # doctest: +SKIP
+        ...     df1.to_excel(writer, sheet_name="Sheet_name_1")
+        ...     df2.to_excel(writer, sheet_name="Sheet_name_2")
+
+        ExcelWriter can also be used to append to an existing Excel file:
+
+        >>> with pd.ExcelWriter("output.xlsx", mode="a") as writer:  # doctest: +SKIP
+        ...     df1.to_excel(writer, sheet_name="Sheet_name_3")
+
+        To set the library that is used to write the Excel file,
+        you can pass the `engine` keyword (the default engine is
+        automatically chosen depending on the file extension):
+
+        >>> df1.to_excel("output1.xlsx", engine="xlsxwriter")  # doctest: +SKIP
+        """
         from pandas.io.formats.excel import ExcelFormatter

         formatter = ExcelFormatter(
@@ -676,8 +747,8 @@ def to_latex(
         ----------
         buf : str, path object, file-like object, or None, default None
             String, path object (implementing ``os.PathLike[str]``), or file-like
-            object implementing a string ``write()`` function. If None, the result is
-            returned as a string.
+            object implementing a string ``write()`` function. If None, the result
+            is returned as a string.
         column_format : str, optional
             The LaTeX column specification placed in location:

@@ -1235,7 +1306,6 @@ def to_typst(
         max_columns: int | None = ...,
     ) -> str: ...

-    [USER_REDACTED](buf=buffering_args, encoding=encoding_args)
     def to_typst(
         self,
         buf: FilePath | WriteBuffer[str] | None = None,
@@ -1253,8 +1323,13 @@ def to_typst(

         Parameters
         ----------
-        %(buf)s
-        %(encoding)s
+        buf : str, path object, file-like object, optional
+            String, path object (implementing ``os.PathLike[str]``), or file-like
+            object implementing a string ``write()`` function. If ``None``, the result
+            is returned as a string.
+        encoding : str, optional
+              Character encoding setting for file output (and meta tags if available).
+              Defaults to ``pandas.options.styler.render.encoding`` value of "utf-8".
         sparse_index : bool, optional
             Whether to sparsify the display of a hierarchical index. Setting to False
             will display each explicit level element in a hierarchical key for each row.
@@ -1354,7 +1429,6 @@ def to_html(
         **kwargs,
     ) -> str: ...

-    [USER_REDACTED](buf=buffering_args, encoding=encoding_args)
     def to_html(
         self,
         buf: FilePath | WriteBuffer[str] | None = None,
@@ -1377,7 +1451,10 @@ def to_html(

         Parameters
         ----------
-        %(buf)s
+        buf : str, path object, file-like object, optional
+            String, path object (implementing ``os.PathLike[str]``), or file-like
+            object implementing a string ``write()`` function. If ``None``, the result
+            is returned as a string.
         table_uuid : str, optional
             Id attribute assigned to the <table> HTML element in the format:

@@ -1412,8 +1489,9 @@ def to_html(
             Rows and columns may be reduced if the number of total elements is
             large. This value is set to ``pandas.options.styler.render.max_elements``,
             which is 262144 (18 bit browser rendering).
-
-        %(encoding)s
+        encoding : str, optional
+              Character encoding setting for file output (and meta tags if available).
+              Defaults to ``pandas.options.styler.render.encoding`` value of "utf-8".
         doctype_html : bool, default False
             Whether to output a fully structured HTML file including all
             HTML elements, or just the core ``<style>`` and ``<table>`` elements.
@@ -1513,7 +1591,6 @@ def to_string(
         delimiter: str = ...,
     ) -> str: ...

-    [USER_REDACTED](buf=buffering_args, encoding=encoding_args)
     def to_string(
         self,
         buf: FilePath | WriteBuffer[str] | None = None,
@@ -1530,8 +1607,13 @@ def to_string(

         Parameters
         ----------
-        %(buf)s
-        %(encoding)s
+        buf : str, path object, file-like object, optional
+            String, path object (implementing ``os.PathLike[str]``), or file-like
+            object implementing a string ``write()`` function. If ``None``, the result
+            is returned as a string.
+        encoding : str, optional
+              Character encoding setting for file output (and meta tags if available).
+              Defaults to ``pandas.options.styler.render.encoding`` value of "utf-8".
         sparse_index : bool, optional
             Whether to sparsify the display of a hierarchical index. Setting to False
             will display each explicit level element in a hierarchical key for each row.
@@ -1899,7 +1981,6 @@ def _apply(
         self._update_ctx(result)
         return self

-    [USER_REDACTED](subset=subset_args)
     def apply(
         self,
         func: Callable,
@@ -1925,7 +2006,10 @@ def apply(
             Apply to each column (``axis=0`` or ``'index'``), to each row
             (``axis=1`` or ``'columns'``), or to the entire DataFrame at once
             with ``axis=None``.
-        %(subset)s
+        subset : label, array-like, IndexSlice, optional
+            A valid 2d input to `DataFrame.loc[<subset>]`, or, in the case of a 1d input
+            or single key, to `DataFrame.loc[:, <subset>]` where the columns are
+            prioritised, to limit ``data`` to *before* applying the function.
         **kwargs : dict
             Pass along to ``func``.

@@ -2010,18 +2094,6 @@ def _apply_index(
         self._update_ctx_header(result, axis)
         return self

-    [USER_REDACTED](
-        this="apply",
-        wise="level-wise",
-        alt="map",
-        altwise="elementwise",
-        func="take a Series and return a string array of the same length",
-        input_note="the index as a Series, if an Index, or a level of a MultiIndex",
-        output_note="an identically sized array of CSS styles as strings",
-        var="label",
-        ret='np.where(label == "B", "background-color: yellow;", "")',
-        ret2='["background-color: yellow;" if "x" in v else "" for v in label]',
-    )
     def apply_index(
         self,
         func: Callable,
@@ -2030,7 +2102,7 @@ def apply_index(
         **kwargs,
     ) -> Styler:
         """
-        Apply a CSS-styling function to the index or column headers, {wise}.
+        Apply a CSS-styling function to the index or column headers, level-wise.

         Updates the HTML representation with the result.

@@ -2040,7 +2112,7 @@ def apply_index(
         Parameters
         ----------
         func : function
-            ``func`` should {func}.
+            ``func`` should take a Series and return a string array of the same length.
         axis : {{0, 1, "index", "columns"}}
             The headers over which to apply the function.
         level : int, str, list, optional
@@ -2055,35 +2127,38 @@ def apply_index(

         See Also
         --------
-        Styler.{alt}_index: Apply a CSS-styling function to headers {altwise}.
+        Styler.map_index: Apply a CSS-styling function to headers elementwise.
         Styler.apply: Apply a CSS-styling function column-wise, row-wise, or table-wise.
         Styler.map: Apply a CSS-styling function elementwise.

         Notes
         -----
-        Each input to ``func`` will be {input_note}. The output of ``func`` should be
-        {output_note}, in the format 'attribute: value; attribute2: value2; ...'
-        or, if nothing is to be applied to that element, an empty string or ``None``.
+        Each input to ``func`` will be the index as a Series, if an Index, or a level
+        of a MultiIndex. The output of ``func`` should be an identically sized array
+        of CSS styles as strings, in the format
+        'attribute: value; attribute2: value2; ...' or, if nothing is to be applied
+        to that element, an empty string or ``None``.

         Examples
         --------
         Basic usage to conditionally highlight values in the index.

         >>> df = pd.DataFrame([[1, 2], [3, 4]], index=["A", "B"])
-        >>> def color_b({var}):
-        ...     return {ret}
-        >>> df.style.{this}_index(color_b)  # doctest: +SKIP
+        >>> def color_b(label):
+        ...     return np.where(label == "B", "background-color: yellow;", "")
+        >>> df.style.apply_index(color_b)  # doctest: +SKIP

         .. figure:: ../../_static/style/appmaphead1.png

         Selectively applying to specific levels of MultiIndex columns.

         >>> midx = pd.MultiIndex.from_product([["ix", "jy"], [0, 1], ["x3", "z4"]])
         >>> df = pd.DataFrame([np.arange(8)], columns=midx)
-        >>> def highlight_x({var}):
-        ...     return {ret2}
-        >>> df.style.{this}_index(
-        ...     highlight_x, axis="columns", level=[0, 2])  # doctest: +SKIP
+        >>> def highlight_x(label):
+        ...     return ["background-color: yellow;" if "x" in v else "" for v in label]
+        >>> df.style.apply_index(
+        ...     highlight_x, axis="columns", level=[0, 2]
+        ... )  # doctest: +SKIP

         .. figure:: ../../_static/style/appmaphead2.png
         """
@@ -2096,26 +2171,73 @@ def apply_index(
         )
         return self

-    [USER_REDACTED](
-        apply_index,
-        this="map",
-        wise="elementwise",
-        alt="apply",
-        altwise="level-wise",
-        func="take a scalar and return a string",
-        input_note="an index value, if an Index, or a level value of a MultiIndex",
-        output_note="CSS styles as a string",
-        var="label",
-        ret='"background-color: yellow;" if label == "B" else None',
-        ret2='"background-color: yellow;" if "x" in label else None',
-    )
     def map_index(
         self,
         func: Callable,
         axis: AxisInt | str = 0,
         level: Level | list[Level] | None = None,
         **kwargs,
     ) -> Styler:
+        """
+        Apply a CSS-styling function to the index or column headers, elementwise.
+
+        Updates the HTML representation with the result.
+
+        .. versionadded:: 2.1.0
+           Styler.applymap_index was deprecated and renamed to Styler.map_index.
+
+        Parameters
+        ----------
+        func : function
+            ``func`` should take a scalar and return a string.
+        axis : {{0, 1, "index", "columns"}}
+            The headers over which to apply the function.
+        level : int, str, list, optional
+            If index is MultiIndex the level(s) over which to apply the function.
+        **kwargs : dict
+            Pass along to ``func``.
+
+        Returns
+        -------
+        Styler
+            Instance of class with CSS applied to its HTML representation.
+
+        See Also
+        --------
+        Styler.apply_index: Apply a CSS-styling function to headers level-wise.
+        Styler.apply: Apply a CSS-styling function column-wise, row-wise, or table-wise.
+        Styler.map: Apply a CSS-styling function elementwise.
+
+        Notes
+        -----
+        Each input to ``func`` will be an index value, if an Index, or a level value of
+        a MultiIndex. The output of ``func`` should be CSS styles as a string, in the
+        format 'attribute: value; attribute2: value2; ...' or, if nothing is to be
+        applied to that element, an empty string or ``None``.
+
+        Examples
+        --------
+        Basic usage to conditionally highlight values in the index.
+
+        >>> df = pd.DataFrame([[1, 2], [3, 4]], index=["A", "B"])
+        >>> def color_b(label):
+        ...     return "background-color: yellow;" if label == "B" else None
+        >>> df.style.map_index(color_b)  # doctest: +SKIP
+
+        .. figure:: ../../_static/style/appmaphead1.png
+
+        Selectively applying to specific levels of MultiIndex columns.
+
+        >>> midx = pd.MultiIndex.from_product([["ix", "jy"], [0, 1], ["x3", "z4"]])
+        >>> df = pd.DataFrame([np.arange(8)], columns=midx)
+        >>> def highlight_x(label):
+        ...     return "background-color: yellow;" if "x" in label else None
+        >>> df.style.map_index(
+        ...     highlight_x, axis="columns", level=[0, 2]
+        ... )  # doctest: +SKIP
+
+        .. figure:: ../../_static/style/appmaphead2.png
+        """
         self._todo.append(
             (
                 lambda instance: instance._apply_index,
@@ -2134,7 +2256,6 @@ def _map(self, func: Callable, subset: Subset | None = None, **kwargs) -> Styler
         self._update_ctx(result)
         return self

-    [USER_REDACTED](subset=subset_args)
     def map(self, func: Callable, subset: Subset | None = None, **kwargs) -> Styler:
         """
         Apply a CSS-styling function elementwise.
@@ -2145,7 +2266,10 @@ def map(self, func: Callable, subset: Subset | None = None, **kwargs) -> Styler:
         ----------
         func : function
             ``func`` should take a scalar and return a string.
-        %(subset)s
+        subset : label, array-like, IndexSlice, optional
+            A valid 2d input to `DataFrame.loc[<subset>]`, or, in the case of a 1d input
+            or single key, to `DataFrame.loc[:, <subset>]` where the columns are
+            prioritised, to limit ``data`` to *before* applying the function.
         **kwargs : dict
             Pass along to ``func``.

@@ -2940,16 +3064,6 @@ def _get_numeric_subset_default(self):
         # boolean column labels (GH47838).
         return self.data.columns.isin(self.data.select_dtypes(include=np.number))

-    [USER_REDACTED](
-        name="background",
-        alt="text",
-        image_prefix="bg",
-        text_threshold="""text_color_threshold : float or int\n
-            Luminance threshold for determining text color in [0, 1]. Facilitates text\n
-            visibility across varying background colors. All text is dark if 0, and\n
-            light if 1, defaults to 0.408.""",
-    )
-    [USER_REDACTED](subset=subset_args)
     def background_gradient(
         self,
         cmap: str | Colormap = "PuBu",
@@ -2963,9 +3077,9 @@ def background_gradient(
         gmap: Sequence | None = None,
     ) -> Styler:
         """
-        Color the {name} in a gradient style.
+        Color the background in a gradient style.

-        The {name} color is determined according
+        The background color is determined according
         to the data in each column, row or frame, or by a given
         gradient map. Requires matplotlib.

@@ -2985,16 +3099,22 @@ def background_gradient(
             Apply to each column (``axis=0`` or ``'index'``), to each row
             (``axis=1`` or ``'columns'``), or to the entire DataFrame at once
             with ``axis=None``.
-        %(subset)s
-        {text_threshold}
+        subset : label, array-like, IndexSlice, optional
+            A valid 2d input to `DataFrame.loc[<subset>]`, or, in the case of a 1d input
+            or single key, to `DataFrame.loc[:, <subset>]` where the columns are
+            prioritised, to limit ``data`` to *before* applying the function.
+        text_color_threshold : float or int
+            Luminance threshold for determining text color in [0, 1]. Facilitates text
+            visibility across varying background colors. All text is dark if 0, and
+            light if 1, defaults to 0.408.
         vmin : float, optional
             Minimum data value that corresponds to colormap minimum value.
             If not specified the minimum value of the data (or gmap) will be used.
         vmax : float, optional
             Maximum data value that corresponds to colormap maximum value.
             If not specified the maximum value of the data (or gmap) will be used.
         gmap : array-like, optional
-            Gradient map for determining the {name} colors. If not supplied
+            Gradient map for determining the background colors. If not supplied
             will use the underlying data from rows, columns or frame. If given as an
             ndarray or list-like must be an identical shape to the underlying data
             considering ``axis`` and ``subset``. If given as DataFrame or Series must
@@ -3005,11 +3125,11 @@ def background_gradient(
         Returns
         -------
         Styler
-            Instance of class with {name} colored in gradient style.
+            Instance of class with background colored in gradient style.

         See Also
         --------
-        Styler.{alt}_gradient: Color the {alt} in a gradient style.
+        Styler.text_gradient: Color the text in a gradient style.

         Notes
         -----
@@ -3039,44 +3159,51 @@ def background_gradient(

         Shading the values column-wise, with ``axis=0``, preselecting numeric columns

-        >>> df.style.{name}_gradient(axis=0)  # doctest: +SKIP
+        >>> df.style.background_gradient(axis=0)  # doctest: +SKIP

-        .. figure:: ../../_static/style/{image_prefix}_ax0.png
+        .. figure:: ../../_static/style/bg_ax0.png

         Shading all values collectively using ``axis=None``

-        >>> df.style.{name}_gradient(axis=None)  # doctest: +SKIP
+        >>> df.style.background_gradient(axis=None)  # doctest: +SKIP

-        .. figure:: ../../_static/style/{image_prefix}_axNone.png
+        .. figure:: ../../_static/style/bg_axNone.png

         Compress the color map from the both ``low`` and ``high`` ends

-        >>> df.style.{name}_gradient(axis=None, low=0.75, high=1.0)  # doctest: +SKIP
+        >>> df.style.background_gradient(
+        ...     axis=None, low=0.75, high=1.0
+        ... )  # doctest: +SKIP

-        .. figure:: ../../_static/style/{image_prefix}_axNone_lowhigh.png
+        .. figure:: ../../_static/style/bg_axNone_lowhigh.png

         Manually setting ``vmin`` and ``vmax`` gradient thresholds

-        >>> df.style.{name}_gradient(axis=None, vmin=6.7, vmax=21.6)  # doctest: +SKIP
+        >>> df.style.background_gradient(
+        ...     axis=None, vmin=6.7, vmax=21.6
+        ... )  # doctest: +SKIP

-        .. figure:: ../../_static/style/{image_prefix}_axNone_vminvmax.png
+        .. figure:: ../../_static/style/bg_axNone_vminvmax.png

         Setting a ``gmap`` and applying to all columns with another ``cmap``

-        >>> df.style.{name}_gradient(axis=0, gmap=df['Temp (c)'], cmap='YlOrRd')
+        >>> df.style.background_gradient(axis=0, gmap=df["Temp (c)"], cmap="YlOrRd")
         ... # doctest: +SKIP

-        .. figure:: ../../_static/style/{image_prefix}_gmap.png
+        .. figure:: ../../_static/style/bg_gmap.png

         Setting the gradient map for a dataframe (i.e. ``axis=None``), we need to
         explicitly state ``subset`` to match the ``gmap`` shape

         >>> gmap = np.array([[1, 2, 3], [2, 3, 4], [3, 4, 5]])
-        >>> df.style.{name}_gradient(axis=None, gmap=gmap,
-        ...     cmap='YlOrRd', subset=['Temp (c)', 'Rain (mm)', 'Wind (m/s)']
+        >>> df.style.background_gradient(
+        ...     axis=None,
+        ...     gmap=gmap,
+        ...     cmap="YlOrRd",
+        ...     subset=["Temp (c)", "Rain (mm)", "Wind (m/s)"],
         ... )  # doctest: +SKIP

-        .. figure:: ../../_static/style/{image_prefix}_axNone_gmap.png
+        .. figure:: ../../_static/style/bg_axNone_gmap.png
         """
         if subset is None and gmap is None:
             subset = self._get_numeric_subset_default()
@@ -3095,13 +3222,6 @@ def background_gradient(
         )
         return self

-    [USER_REDACTED](
-        background_gradient,
-        name="text",
-        alt="background",
-        image_prefix="tg",
-        text_threshold="",
-    )
     def text_gradient(
         self,
         cmap: str | Colormap = "PuBu",
@@ -3113,6 +3233,127 @@ def text_gradient(
         vmax: float | None = None,
         gmap: Sequence | None = None,
     ) -> Styler:
+        """
+        Color the text in a gradient style.
+
+        The text color is determined according
+        to the data in each column, row or frame, or by a given
+        gradient map. Requires matplotlib.
+
+        Parameters
+        ----------
+        cmap : str or colormap
+            Matplotlib colormap.
+        low : float
+            Compress the color range at the low end. This is a multiple of the data
+            range to extend below the minimum; good values usually in [0, 1],
+            defaults to 0.
+        high : float
+            Compress the color range at the high end. This is a multiple of the data
+            range to extend above the maximum; good values usually in [0, 1],
+            defaults to 0.
+        axis : {{0, 1, "index", "columns", None}}, default 0
+            Apply to each column (``axis=0`` or ``'index'``), to each row
+            (``axis=1`` or ``'columns'``), or to the entire DataFrame at once
+            with ``axis=None``.
+        subset : label, array-like, IndexSlice, optional
+            A valid 2d input to `DataFrame.loc[<subset>]`, or, in the case of a 1d input
+            or single key, to `DataFrame.loc[:, <subset>]` where the columns are
+            prioritised, to limit ``data`` to *before* applying the function.
+        vmin : float, optional
+            Minimum data value that corresponds to colormap minimum value.
+            If not specified the minimum value of the data (or gmap) will be used.
+        vmax : float, optional
+            Maximum data value that corresponds to colormap maximum value.
+            If not specified the maximum value of the data (or gmap) will be used.
+        gmap : array-like, optional
+            Gradient map for determining the text colors. If not supplied
+            will use the underlying data from rows, columns or frame. If given as an
+            ndarray or list-like must be an identical shape to the underlying data
+            considering ``axis`` and ``subset``. If given as DataFrame or Series must
+            have same index and column labels considering ``axis`` and ``subset``.
+            If supplied, ``vmin`` and ``vmax`` should be given relative to this
+            gradient map.
+
+        Returns
+        -------
+        Styler
+            Instance of class with background colored in gradient style.
+
+        See Also
+        --------
+        Styler.background_gradient: Color the background in a gradient style.
+
+        Notes
+        -----
+        When using ``low`` and ``high`` the range
+        of the gradient, given by [NAME_REDACTED] ``gmap`` is not given or by ``gmap``,
+        is extended at the low end effectively by
+        `map.min - low * map.range` and at the high end by
+        `map.max + high * map.range` before the colors are normalized and determined.
+
+        If combining with ``vmin`` and ``vmax`` the `map.min`, `map.max` and
+        `map.range` are replaced by [NAME_REDACTED] values derived from
+        ``vmin`` and ``vmax``.
+
+        This method will preselect numeric columns and ignore non-numeric columns
+        unless a ``gmap`` is supplied in which case no preselection occurs.
+
+        Examples
+        --------
+        >>> df = pd.DataFrame(
+        ...     columns=["City", "Temp (c)", "Rain (mm)", "Wind (m/s)"],
+        ...     data=[
+        ...         ["Stockholm", 21.6, 5.0, 3.2],
+        ...         ["Oslo", 22.4, 13.3, 3.1],
+        ...         ["Copenhagen", 24.5, 0.0, 6.7],
+        ...     ],
+        ... )
+
+        Shading the values column-wise, with ``axis=0``, preselecting numeric columns
+
+        >>> df.style.text_gradient(axis=0)  # doctest: +SKIP
+
+        .. figure:: ../../_static/style/tg_ax0.png
+
+        Shading all values collectively using ``axis=None``
+
+        >>> df.style.text_gradient(axis=None)  # doctest: +SKIP
+
+        .. figure:: ../../_static/style/tg_axNone.png
+
+        Compress the color map from the both ``low`` and ``high`` ends
+
+        >>> df.style.text_gradient(axis=None, low=0.75, high=1.0)  # doctest: +SKIP
+
+        .. figure:: ../../_static/style/tg_axNone_lowhigh.png
+
+        Manually setting ``vmin`` and ``vmax`` gradient thresholds
+
+        >>> df.style.text_gradient(axis=None, vmin=6.7, vmax=21.6)  # doctest: +SKIP
+
+        .. figure:: ../../_static/style/tg_axNone_vminvmax.png
+
+        Setting a ``gmap`` and applying to all columns with another ``cmap``
+
+        >>> df.style.text_gradient(axis=0, gmap=df["Temp (c)"], cmap="YlOrRd")
+        ... # doctest: +SKIP
+
+        .. figure:: ../../_static/style/tg_gmap.png
+
+        Setting the gradient map for a dataframe (i.e. ``axis=None``), we need to
+        explicitly state ``subset`` to match the ``gmap`` shape
+
+        >>> gmap = np.array([[1, 2, 3], [2, 3, 4], [3, 4, 5]])
+        >>> df.style.text_gradient(
+        ...     axis=None,
+        ...     gmap=gmap,
+        ...     cmap="YlOrRd",
+        ...     subset=["Temp (c)", "Rain (mm)", "Wind (m/s)"],
+        ... )  # doctest: +SKIP
+
+        .. figure:: ../../_static/style/tg_axNone_gmap.png
+        """
         if subset is None and gmap is None:
             subset = self._get_numeric_subset_default()

@@ -3129,14 +3370,16 @@ def text_gradient(
             text_only=True,
         )

-    [USER_REDACTED](subset=subset_args)
     def set_properties(self, subset: Subset | None = None, **kwargs) -> Styler:
         """
         Set defined CSS-properties to each ``<td>`` HTML element for the given subset.

         Parameters
         ----------
-        %(subset)s
+        subset : label, array-like, IndexSlice, optional
+            A valid 2d input to `DataFrame.loc[<subset>]`, or, in the case of a 1d input
+            or single key, to `DataFrame.loc[:, <subset>]` where the columns are
+            prioritised, to limit ``data`` to *before* applying the function.
         **kwargs : dict
             A dictionary of property, value pairs to be set for each cell.

@@ -3168,7 +3411,6 @@ def set_properties(self, subset: Subset | None = None, **kwargs) -> Styler:
         values = "".join([f"{p}: {v};" for p, v in kwargs.items()])
         return self.map(lambda x: values, subset=subset)

-    [USER_REDACTED](subset=subset_args)
     def bar(
         self,
         subset: Subset | None = None,
@@ -3188,7 +3430,10 @@ def bar(

         Parameters
         ----------
-        %(subset)s
+        subset : label, array-like, IndexSlice, optional
+            A valid 2d input to `DataFrame.loc[<subset>]`, or, in the case of a 1d input
+            or single key, to `DataFrame.loc[:, <subset>]` where the columns are
+            prioritised, to limit ``data`` to *before* applying the function.
         axis : {0 or 'index', 1 or 'columns', None}, default 0
             Apply to each column (``axis=0`` or ``'index'``), to each row
             (``axis=1`` or ``'columns'``), or to the entire DataFrame at once
@@ -3293,11 +3538,6 @@ def bar(

         return self

-    [USER_REDACTED](
-        subset=subset_args,
-        props=properties_args,
-        color=coloring_args.format(default="red"),
-    )
     def highlight_null(
         self,
         color: str = "red",
@@ -3309,11 +3549,15 @@ def highlight_null(

         Parameters
         ----------
-        %(color)s
-
-        %(subset)s
-
-        %(props)s
+        color : str, default 'red'
+           Background color to use for highlighting.
+        subset : label, array-like, IndexSlice, optional
+            A valid 2d input to `DataFrame.loc[<subset>]`, or, in the case of a 1d input
+            or single key, to `DataFrame.loc[:, <subset>]` where the columns are
+            prioritised, to limit ``data`` to *before* applying the function.
+        props : str, default None
+           CSS properties to use for highlighting. If ``props`` is given, ``color``
+           is not used.

         Returns
         -------
@@ -3343,11 +3587,6 @@ def f(data: DataFrame, props: str) -> np.ndarray:
             props = f"background-color: {color};"
         return self.apply(f, axis=None, subset=subset, props=props)

-    [USER_REDACTED](
-        subset=subset_args,
-        color=coloring_args.format(default="yellow"),
-        props=properties_args,
-    )
     def highlight_max(
         self,
         subset: Subset | None = None,
@@ -3360,13 +3599,19 @@ def highlight_max(

         Parameters
         ----------
-        %(subset)s
-        %(color)s
+        subset : label, array-like, IndexSlice, optional
+            A valid 2d input to `DataFrame.loc[<subset>]`, or, in the case of a 1d input
+            or single key, to `DataFrame.loc[:, <subset>]` where the columns are
+            prioritised, to limit ``data`` to *before* applying the function.
+        color : str, default 'yellow'
+           Background color to use for highlighting.
         axis : {0 or 'index', 1 or 'columns', None}, default 0
             Apply to each column (``axis=0`` or ``'index'``), to each row
             (``axis=1`` or ``'columns'``), or to the entire DataFrame at once
             with ``axis=None``.
-        %(props)s
+        props : str, default None
+           CSS properties to use for highlighting. If ``props`` is given, ``color``
+           is not used.

         Returns
         -------
@@ -3398,11 +3643,6 @@ def highlight_max(
             props=props,
         )

-    [USER_REDACTED](
-        subset=subset_args,
-        color=coloring_args.format(default="yellow"),
-        props=properties_args,
-    )
     def highlight_min(
         self,
         subset: Subset | None = None,
@@ -3415,13 +3655,19 @@ def highlight_min(

         Parameters
         ----------
-        %(subset)s
-        %(color)s
+        subset : label, array-like, IndexSlice, optional
+            A valid 2d input to `DataFrame.loc[<subset>]`, or, in the case of a 1d input
+            or single key, to `DataFrame.loc[:, <subset>]` where the columns are
+            prioritised, to limit ``data`` to *before* applying the function.
+        color : str, default 'yellow'
+           Background color to use for highlighting.
         axis : {0 or 'index', 1 or 'columns', None}, default 0
             Apply to each column (``axis=0`` or ``'index'``), to each row
             (``axis=1`` or ``'columns'``), or to the entire DataFrame at once
             with ``axis=None``.
-        %(props)s
+        props : str, default None
+           CSS properties to use for highlighting. If ``props`` is given, ``color``
+           is not used.

         Returns
         -------
@@ -3453,11 +3699,6 @@ def highlight_min(
             props=props,
         )

-    [USER_REDACTED](
-        subset=subset_args,
-        color=coloring_args.format(default="yellow"),
-        props=properties_args,
-    )
     def highlight_between(
         self,
         subset: Subset | None = None,
@@ -3473,8 +3714,12 @@ def highlight_between(

         Parameters
         ----------
-        %(subset)s
-        %(color)s
+        subset : label, array-like, IndexSlice, optional
+            A valid 2d input to `DataFrame.loc[<subset>]`, or, in the case of a 1d input
+            or single key, to `DataFrame.loc[:, <subset>]` where the columns are
+            prioritised, to limit ``data`` to *before* applying the function.
+        color : str, default 'yellow'
+           Background color to use for highlighting.
         axis : {0 or 'index', 1 or 'columns', None}, default 0
             If ``left`` or ``right`` given as sequence, axis along which to apply those
             boundaries. See examples.
@@ -3484,7 +3729,9 @@ def highlight_between(
             Right bound for defining the range.
         inclusive : {'both', 'neither', 'left', 'right'}
             Identify whether bounds are closed or open.
-        %(props)s
+        props : str, default None
+           CSS properties to use for highlighting. If ``props`` is given, ``color``
+           is not used.

         Returns
         -------
@@ -3568,11 +3815,6 @@ def highlight_between(
             inclusive=inclusive,
         )

-    [USER_REDACTED](
-        subset=subset_args,
-        color=coloring_args.format(default="yellow"),
-        props=properties_args,
-    )
     def highlight_quantile(
         self,
         subset: Subset | None = None,
@@ -3589,8 +3831,12 @@ def highlight_quantile(

         Parameters
         ----------
-        %(subset)s
-        %(color)s
+        subset : label, array-like, IndexSlice, optional
+            A valid 2d input to `DataFrame.loc[<subset>]`, or, in the case of a 1d input
+            or single key, to `DataFrame.loc[:, <subset>]` where the columns are
+            prioritised, to limit ``data`` to *before* applying the function.
+        color : str, default 'yellow'
+            Background color to use for highlighting.
         axis : {0 or 'index', 1 or 'columns', None}, default 0
             Axis along which to determine and highlight quantiles. If ``None`` quantiles
             are measured over the entire DataFrame. See examples.
@@ -3603,7 +3849,9 @@ def highlight_quantile(
             quantile estimation.
         inclusive : {'both', 'neither', 'left', 'right'}
             Identify whether quantile bounds are closed or open.
-        %(props)s
+        props : str, default None
+            CSS properties to use for highlighting. If ``props`` is given, ``color``
+            is not used.

         Returns
         -------

```suggestion
```


DOC: Inline docstring for str.rpartition

Replaces [USER_REDACTED] usage with hardcoded docstring in pandas/core/strings/accessor.py.

- [x] closes #62437 (Replace xxxx with the GitHub issue number)
- [x] [Tests added and passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#writing-tests) if fixing a bug or adding a new feature
- [x] All [code checks passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#pre-commit).
- [ ] Added [type annotations](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#type-hints) to new arguments/methods/functions.
- [ ] Added an entry in the latest `doc/source/whatsnew/vX.X.X.rst` file if fixing a bug or adding a new feature.
- [x] If I used AI to develop this pull request, I prompted it to follow `AGENTS.md`.

@@ -1038,17 +1038,89 @@ def partition(self, sep: str = " ", expand: bool = True):
             result, expand=expand, returns_string=expand, dtype=dtype
         )

-    [USER_REDACTED](
-        _shared_docs["str_partition"]
-        % {
-            "side": "last",
-            "return": "3 elements containing two empty strings, followed by the "
-            "string itself",
-            "also": "partition : Split the string at the first occurrence of `sep`.",
-        }
-    )
     [USER_REDACTED]_nonstring_types(["bytes"])
     def rpartition(self, sep: str = " ", expand: bool = True):
+        """
+        Split the string at the last occurrence of `sep`.
+
+        This method splits the string at the last occurrence of `sep`,
+        and returns 3 elements containing the part before the separator,
+        the separator itself, and the part after the separator.
+        If the separator is not found, return 3 elements containing two empty strings,
+        followed by [NAME_REDACTED]
+
+        Parameters
+        ----------
+        sep : str, default " "
+            String to split on.
+        expand : bool, default True
+            If True, return DataFrame/MultiIndex expanding dimensionality.
+            If False, return Series/Index.
+
+        Returns
+        -------
+        DataFrame/MultiIndex or Series/Index of objects
+            Returns appropriate type based on `expand` parameter with strings
+            split based on the `sep` parameter.
+
+        See Also
+        --------
+        partition : Split the string at the first occurrence of `sep`.
+        Series.str.split : Split strings around given separators.
+        str.partition : Standard library version.
+
+        Examples
+        --------
+        >>> s = pd.Series(["Linda van der Berg", "[NAME_REDACTED]"])
+        >>> s
+        0    Linda van der Berg
+        1    [NAME_REDACTED]
+        dtype: str
+
+        >>> s.str.partition()
+                0  1             2
+        0   Linda     van der Berg
+        1  [NAME_REDACTED]
+
+        To partition by [NAME_REDACTED] of the first one:
+
+        >>> s.str.rpartition()
+                       0  1            2
+        0  Linda van der            Berg
+        1         [NAME_REDACTED]
+
+        To partition by [NAME_REDACTED] a space:
+
+        >>> s.str.partition("-")
+                            0  1       2
+        0  Linda van der Berg
+        1         [NAME_REDACTED]  -  Rivers
+
+        To return a Series containing tuples instead of a DataFrame:
+
+        >>> s.str.partition("-", expand=False)
+        0    (Linda van der Berg, , )
+        1    ([NAME_REDACTED], -, Rivers)
+        dtype: object
+
+        Also available on indices:
+
+        >>> idx = pd.Index(["X 123", "Y 999"])
+        >>> idx
+        Index(['X 123', 'Y 999'], dtype='str')
+
+        Which will create a MultiIndex:
+
+        >>> idx.str.partition()
+        MultiIndex([('X', ' ', '123'),
+                    ('Y', ' ', '999')],
+                   )
+
+        Or an index with tuples with ``expand=False``:
+
+        >>> idx.str.partition(expand=False)
+        Index([('X', ' ', '123'), ('Y', ' ', '999')], dtype='object')
+        """
         result = self._data.array._str_rpartition(sep, expand)
         if self._data.dtype == "category":
             dtype = self._data.dtype.categories.dtype

Can you avoid the doctest skips in your changes?

Thanks for the suggestion! I’ve removed the doctest: +SKIP markers and updated the example outputs to match the canonical, deterministic repr used elsewhere in accessor.py, so the doctests now pass without skips.
Please let me know if any further adjustments are needed.


DOC: Inline docstring for str.partition

Replaces [USER_REDACTED] usage with hardcoded docstring in pandas/core/strings/accessor.py.

- [x] closes #62437
- [x] [Tests added and passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#writing-tests) if fixing a bug or adding a new feature
- [x] All [code checks passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#pre-commit).
- [ ] Added [type annotations](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#type-hints) to new arguments/methods/functions.
- [ ] Added an entry in the latest `doc/source/whatsnew/vX.X.X.rst` file if fixing a bug or adding a new feature.
- [x] If I used AI to develop this pull request, I prompted it to follow `AGENTS.md`.

@@ -1018,17 +1018,89 @@ def rsplit(self, pat=None, *, n=-1, expand: bool = False):
     Index([('X', ' ', '123'), ('Y', ' ', '999')], dtype='object')
     """

-    [USER_REDACTED](
-        _shared_docs["str_partition"]
-        % {
-            "side": "first",
-            "return": "3 elements containing the string itself, followed by two "
-            "empty strings",
-            "also": "rpartition : Split the string at the last occurrence of `sep`.",
-        }
-    )
     [USER_REDACTED]_nonstring_types(["bytes"])
     def partition(self, sep: str = " ", expand: bool = True):
+        """
+        Split the string at the first occurrence of `sep`.
+
+        This method splits the string at the first occurrence of `sep`,
+        and returns 3 elements containing the part before the separator,
+        the separator itself, and the part after the separator.
+        If the separator is not found, return 3 elements containing the string itself,
+        followed by [NAME_REDACTED]
+
+        Parameters
+        ----------
+        sep : str, default whitespace
+            String to split on.
+        expand : bool, default True
+            If True, return DataFrame/MultiIndex expanding dimensionality.
+            If False, return Series/Index.
+
+        Returns
+        -------
+        DataFrame/MultiIndex or Series/Index of objects
+            Returns appropriate type based on `expand` parameter with strings
+            split based on the `sep` parameter.
+
+        See Also
+        --------
+        rpartition : Split the string at the last occurrence of `sep`.
+        Series.str.split : Split strings around given separators.
+        str.partition : Standard library version.
+
+        Examples
+        --------
+        >>> s = pd.Series(["Linda van der Berg", "[NAME_REDACTED]"])
+        >>> s
+        0    Linda van der Berg
+        1    [NAME_REDACTED]
+        dtype: str
+
+        >>> s.str.partition()
+                0  1             2
+        0   Linda     van der Berg
+        1  [NAME_REDACTED]
+
+        To partition by [NAME_REDACTED] of the first one:
+
+        >>> s.str.rpartition()
+                       0  1            2
+        0  Linda van der            Berg
+        1         [NAME_REDACTED]
+
+        To partition by [NAME_REDACTED] a space:
+
+        >>> s.str.partition("-")
+                            0  1       2
+        0  Linda van der Berg
+        1         [NAME_REDACTED]  -  Rivers
+
+        To return a Series containing tuples instead of a DataFrame:
+
+        >>> s.str.partition("-", expand=False)
+        0    (Linda van der Berg, , )
+        1    ([NAME_REDACTED], -, Rivers)
+        dtype: object
+
+        Also available on indices:
+
+        >>> idx = pd.Index(["X 123", "Y 999"])
+        >>> idx
+        Index(['X 123', 'Y 999'], dtype='str')
+
+        Which will create a MultiIndex:
+
+        >>> idx.str.partition()
+        MultiIndex([('X', ' ', '123'),
+                    ('Y', ' ', '999')],
+                   )
+
+        Or an index with tuples with ``expand=False``:
+
+        >>> idx.str.partition(expand=False)
+        Index([('X', ' ', '123'), ('Y', ' ', '999')], dtype='object')
+        """
         result = self._data.array._str_partition(sep, expand)
         if self._data.dtype == "category":
             dtype = self._data.dtype.categories.dtype


ENH: Add strict=True to zip() calls in pandas/core/reshape/

Added strict=True to all zip() calls in the pandas/core/reshape/.

Updated files:
- pandas/core/reshape/melt.py - 1 zip() call
- pandas/core/reshape/reshape.py- 4 zip() calls

Removed these files from the B905 ignore list in pyproject.toml.

Related to #62434

@@ -696,7 +696,9 @@ def stack_factorize(index):
             levels=new_levels, codes=new_codes, names=new_names, verify_integrity=False
         )
     else:
-        levels, (ilab, clab) = zip(*map(stack_factorize, (frame.index, frame.columns)))
+        levels, (ilab, clab) = zip(
+            *map(stack_factorize, (frame.index, frame.columns)), strict=True
+        )
         codes = ilab.repeat(K), np.tile(clab, N).ravel()
         new_index = MultiIndex(
             levels=levels,
@@ -782,17 +784,17 @@ def _stack_multi_column_index(columns: MultiIndex) -> MultiIndex | Index:
     )

     # Remove duplicate tuples in the MultiIndex.
-    tuples = zip(*levs)
+    tuples = zip(*levs, strict=True)
     unique_tuples = (key for key, _ in itertools.groupby(tuples))
-    new_levs = zip(*unique_tuples)
+    new_levs = zip(*unique_tuples, strict=True)

     # The dtype of each level must be explicitly set to avoid inferring the wrong type.
     # See GH-36991.
     return MultiIndex.from_arrays(
         [
             # Not all indices can accept None values.
             Index(new_lev, dtype=lev.dtype) if None not in new_lev else new_lev
-            for new_lev, lev in zip(new_levs, columns.levels)
+            for new_lev, lev in zip(new_levs, columns.levels[:-1], strict=True)
         ],
         names=columns.names[:-1],
     )

@@ -444,7 +444,6 @@ exclude = [
 # For contributors working on this issue:
 # After adding strict={True,False} to zip() calls in a file,
 # remove its line from this section
-"pandas/core/reshape/reshape.py" = ["B905"]
 "pandas/tests/frame/conftest.py" = ["B905"]
 "pandas/tests/frame/constructors/test_from_dict.py" = ["B905"]
 "pandas/tests/frame/indexing/test_delitem.py" = ["B905"]

Why were these added?

Thanks for catching this. Those lines (447-459) were accidentally left from a merge conflict resolution.

Also, the main purpose of this PR was to remove pandas/core/reshape/reshape.py  from the ignore list since I've fixed all zip() calls in that file by [NAME_REDACTED]=True.

I've now removed lines 447-460 entirely.