Skip to content

TYP: Remove NDFrame._add_series_or_dataframe_operations #35957

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion pandas/core/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -9306,7 +9306,6 @@ def _AXIS_NAMES(self) -> Dict[int, str]:


DataFrame._add_numeric_operations()
DataFrame._add_series_or_dataframe_operations()

ops.add_flex_arithmetic_methods(DataFrame)
ops.add_special_arithmetic_methods(DataFrame)
Expand Down
294 changes: 67 additions & 227 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import operator
import pickle
import re
from textwrap import dedent
from typing import (
TYPE_CHECKING,
Any,
Expand Down Expand Up @@ -101,6 +100,7 @@
from pandas.core.missing import find_valid_index
from pandas.core.ops import _align_method_FRAME
from pandas.core.shared_docs import _shared_docs
from pandas.core.window import Expanding, ExponentialMovingWindow, Rolling, Window

from pandas.io.formats import format as fmt
from pandas.io.formats.format import DataFrameFormatter, format_percentiles
Expand All @@ -109,9 +109,12 @@
if TYPE_CHECKING:
from pandas.core.resample import Resampler
from pandas.core.series import Series # noqa: F401
from pandas.core.window.indexers import BaseIndexer
from pandas._libs.tslibs import BaseOffset

# goal is to be able to define the docs close to function, while still being
# able to share
_shared_docs = {**_shared_docs}
_shared_doc_kwargs = dict(
axes="keywords for axes",
klass="Series/DataFrame",
Expand Down Expand Up @@ -5127,51 +5130,6 @@ def pipe(self, func, *args, **kwargs):
"""
return com.pipe(self, func, *args, **kwargs)

_shared_docs["aggregate"] = dedent(
"""
Aggregate using one or more operations over the specified axis.
{versionadded}
Parameters
----------
func : function, str, list or dict
Function to use for aggregating the data. If a function, must either
work when passed a {klass} or when passed to {klass}.apply.

Accepted combinations are:

- function
- string function name
- list of functions and/or function names, e.g. ``[np.sum, 'mean']``
- dict of axis labels -> functions, function names or list of such.
{axis}
*args
Positional arguments to pass to `func`.
**kwargs
Keyword arguments to pass to `func`.

Returns
-------
scalar, Series or DataFrame

The return can be:

* scalar : when Series.agg is called with single function
* Series : when DataFrame.agg is called with a single function
* DataFrame : when DataFrame.agg is called with several functions

Return scalar, Series or DataFrame.
{see_also}
Notes
-----
`agg` is an alias for `aggregate`. Use the alias.

In pandas, agg, as most operations just ignores the missing values,
and returns the operation only considering the values that are present.

A passed user-defined-function will be passed a Series for evaluation.
{examples}"""
)

# ----------------------------------------------------------------------
# Attribute access

Expand Down Expand Up @@ -7448,77 +7406,6 @@ def clip(

return result

_shared_docs[
"groupby"
] = """
Group %(klass)s using a mapper or by a Series of columns.

A groupby operation involves some combination of splitting the
object, applying a function, and combining the results. This can be
used to group large amounts of data and compute operations on these
groups.

Parameters
----------
by : mapping, function, label, or list of labels
Used to determine the groups for the groupby.
If ``by`` is a function, it's called on each value of the object's
index. If a dict or Series is passed, the Series or dict VALUES
will be used to determine the groups (the Series' values are first
aligned; see ``.align()`` method). If an ndarray is passed, the
values are used as-is determine the groups. A label or list of
labels may be passed to group by the columns in ``self``. Notice
that a tuple is interpreted as a (single) key.
axis : {0 or 'index', 1 or 'columns'}, default 0
Split along rows (0) or columns (1).
level : int, level name, or sequence of such, default None
If the axis is a MultiIndex (hierarchical), group by a particular
level or levels.
as_index : bool, default True
For aggregated output, return object with group labels as the
index. Only relevant for DataFrame input. as_index=False is
effectively "SQL-style" grouped output.
sort : bool, default True
Sort group keys. Get better performance by turning this off.
Note this does not influence the order of observations within each
group. Groupby preserves the order of rows within each group.
group_keys : bool, default True
When calling apply, add group keys to index to identify pieces.
squeeze : bool, default False
Reduce the dimensionality of the return type if possible,
otherwise return a consistent type.

.. deprecated:: 1.1.0

observed : bool, default False
This only applies if any of the groupers are Categoricals.
If True: only show observed values for categorical groupers.
If False: show all values for categorical groupers.

.. versionadded:: 0.23.0
dropna : bool, default True
If True, and if group keys contain NA values, NA values together
with row/column will be dropped.
If False, NA values will also be treated as the key in groups

.. versionadded:: 1.1.0

Returns
-------
%(klass)sGroupBy
Returns a groupby object that contains information about the groups.

See Also
--------
resample : Convenience method for frequency conversion and resampling
of time series.

Notes
-----
See the `user guide
<https://pandas.pydata.org/pandas-docs/stable/groupby.html>`_ for more.
"""

def asfreq(
self: FrameOrSeries,
freq,
Expand Down Expand Up @@ -8427,35 +8314,6 @@ def ranker(data):

return ranker(data)

_shared_docs[
"compare"
] = """
Compare to another %(klass)s and show the differences.

.. versionadded:: 1.1.0

Parameters
----------
other : %(klass)s
Object to compare with.

align_axis : {0 or 'index', 1 or 'columns'}, default 1
Determine which axis to align the comparison on.

* 0, or 'index' : Resulting differences are stacked vertically
with rows drawn alternately from self and other.
* 1, or 'columns' : Resulting differences are aligned horizontally
with columns drawn alternately from self and other.

keep_shape : bool, default False
If true, all rows and columns are kept.
Otherwise, only the ones with different values are kept.

keep_equal : bool, default False
If true, the result keeps values that are equal.
Otherwise, equal values are shown as NaNs.
"""

@Appender(_shared_docs["compare"] % _shared_doc_kwargs)
def compare(
self,
Expand Down Expand Up @@ -10585,45 +10443,21 @@ def mad(self, axis=None, skipna=None, level=None):
examples=_min_examples,
)

@classmethod
def _add_series_or_dataframe_operations(cls):
"""
Add the series or dataframe only operations to the cls; evaluate
the doc strings again.
"""
from pandas.core.window import (
Expanding,
ExponentialMovingWindow,
Rolling,
Window,
)

@doc(Rolling)
def rolling(
self,
window,
min_periods=None,
center=False,
win_type=None,
on=None,
axis=0,
closed=None,
):
axis = self._get_axis_number(axis)

if win_type is not None:
return Window(
self,
window=window,
min_periods=min_periods,
center=center,
win_type=win_type,
on=on,
axis=axis,
closed=closed,
)
@doc(Rolling)
def rolling(
self,
window: "Union[int, timedelta, BaseOffset, BaseIndexer]",
min_periods: Optional[int] = None,
center: bool_t = False,
win_type: Optional[str] = None,
on: Optional[str] = None,
axis: Axis = 0,
closed: Optional[str] = None,
):
axis = self._get_axis_number(axis)

return Rolling(
if win_type is not None:
return Window(
self,
window=window,
min_periods=min_periods,
Expand All @@ -10634,53 +10468,59 @@ def rolling(
closed=closed,
)

cls.rolling = rolling

@doc(Expanding)
def expanding(self, min_periods=1, center=None, axis=0):
axis = self._get_axis_number(axis)
if center is not None:
warnings.warn(
"The `center` argument on `expanding` "
"will be removed in the future",
FutureWarning,
stacklevel=2,
)
else:
center = False
return Rolling(
self,
window=window,
min_periods=min_periods,
center=center,
win_type=win_type,
on=on,
axis=axis,
closed=closed,
)

return Expanding(self, min_periods=min_periods, center=center, axis=axis)
@doc(Expanding)
def expanding(
self, min_periods: int = 1, center: Optional[bool_t] = None, axis: Axis = 0
) -> Expanding:
axis = self._get_axis_number(axis)
if center is not None:
warnings.warn(
"The `center` argument on `expanding` will be removed in the future",
FutureWarning,
stacklevel=2,
)
else:
center = False

cls.expanding = expanding
return Expanding(self, min_periods=min_periods, center=center, axis=axis)

@doc(ExponentialMovingWindow)
def ewm(
@doc(ExponentialMovingWindow)
def ewm(
self,
com: Optional[float] = None,
span: Optional[float] = None,
halflife: Optional[Union[float, TimedeltaConvertibleTypes]] = None,
alpha: Optional[float] = None,
min_periods: int = 0,
adjust: bool_t = True,
ignore_na: bool_t = False,
axis: Axis = 0,
times: Optional[Union[str, np.ndarray, FrameOrSeries]] = None,
) -> ExponentialMovingWindow:
axis = self._get_axis_number(axis)
return ExponentialMovingWindow(
self,
com=None,
span=None,
halflife=None,
alpha=None,
min_periods=0,
adjust=True,
ignore_na=False,
axis=0,
times=None,
):
axis = self._get_axis_number(axis)
return ExponentialMovingWindow(
self,
com=com,
span=span,
halflife=halflife,
alpha=alpha,
min_periods=min_periods,
adjust=adjust,
ignore_na=ignore_na,
axis=axis,
times=times,
)

cls.ewm = ewm
com=com,
span=span,
halflife=halflife,
alpha=alpha,
min_periods=min_periods,
adjust=adjust,
ignore_na=ignore_na,
axis=axis,
times=times,
)

@doc(klass=_shared_doc_kwargs["klass"], axis="")
def transform(self, func, *args, **kwargs):
Expand Down
1 change: 0 additions & 1 deletion pandas/core/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -5000,7 +5000,6 @@ def to_period(self, freq=None, copy=True) -> "Series":


Series._add_numeric_operations()
Series._add_series_or_dataframe_operations()

# Add arithmetic!
ops.add_flex_arithmetic_methods(Series)
Expand Down
Loading