from pandas._config.config import option_context as option_context
from pandas._libs import Timestamp as Timestamp
from pandas._typing import FrameOrSeries as FrameOrSeries, Scalar as Scalar
from pandas.core import nanops as nanops
from pandas.core.arrays import Categorical as Categorical, DatetimeArray as DatetimeArray, try_cast_to_ea as try_cast_to_ea
from pandas.core.base import DataError as DataError, PandasObject as PandasObject, SelectionMixin as SelectionMixin
from pandas.core.dtypes.cast import maybe_downcast_to_dtype as maybe_downcast_to_dtype
from pandas.core.dtypes.common import ensure_float as ensure_float, is_datetime64_dtype as is_datetime64_dtype, is_extension_array_dtype as is_extension_array_dtype, is_integer_dtype as is_integer_dtype, is_numeric_dtype as is_numeric_dtype, is_object_dtype as is_object_dtype, is_scalar as is_scalar
from pandas.core.dtypes.missing import isna as isna, notna as notna
from pandas.core.frame import DataFrame as DataFrame
from pandas.core.generic import NDFrame as NDFrame
from pandas.core.groupby import base as base, ops as ops
from pandas.core.indexes.api import CategoricalIndex as CategoricalIndex, Index as Index, MultiIndex as MultiIndex
from pandas.core.series import Series as Series
from pandas.core.sorting import get_group_index_sorter as get_group_index_sorter
from pandas.errors import AbstractMethodError as AbstractMethodError
from pandas.util._decorators import Appender as Appender, Substitution as Substitution, cache_readonly as cache_readonly
from typing import Any, List, Optional, Union, Hashable, Callable, Mapping, TypeVar, Tuple, overload

PipeReturn = TypeVar('PipeReturn')


class GroupByPlot(PandasObject):
    def __init__(self, groupby: Any) -> None: ...
    def __call__(self, *args: Any, **kwargs: Any) -> Any: ...
    def __getattr__(self, name: str) -> Any: ...

_KeysArgType = Union[
    Hashable,
    List[Hashable],
    Callable[[Hashable], Hashable],
    List[Callable[[Hashable], Hashable]],
    Mapping[Hashable, Hashable],
]

class _GroupBy(PandasObject, SelectionMixin):
    level: Any = ...
    as_index: Any = ...
    keys: Any = ...
    sort: Any = ...
    group_keys: Any = ...
    squeeze: Any = ...
    observed: Any = ...
    mutated: Any = ...
    obj: Any = ...
    axis: Any = ...
    grouper: Any = ...
    exclusions: Any = ...
    def __init__(self, obj: NDFrame, keys: Optional[_KeysArgType]=..., axis: int=..., level: Any = ..., grouper: Optional[ops.BaseGrouper]=..., exclusions: Any = ..., selection: Any = ..., as_index: bool=..., sort: bool=..., group_keys: bool=..., squeeze: bool=..., observed: bool=..., mutated: bool=...) -> None: ...
    def __len__(self) -> int: ...
    @property
    def groups(self) -> Any: ...
    @property
    def ngroups(self) -> Any: ...
    @property
    def indices(self) -> Any: ...
    def __getattr__(self, attr: str) -> Any: ...
    @overload
    def pipe(self: Any, func: Union[Callable[..., PipeReturn], Tuple[Callable[..., PipeReturn], str]], *args: Any, **kwargs: Any) -> PipeReturn: ...
    @overload
    def pipe(self: Any, func: PipeReturn, *args: Any, **kwargs: Any) -> PipeReturn: ...
    plot: Any = ...
    def get_group(self, name: Any, obj: Optional[Any] = ...) -> Any: ...
    def __iter__(self) -> Any: ...
    def apply(self, func: Any, *args: Any, **kwargs: Any) -> Any: ...
    def transform(self, func: Any, *args: Any, **kwargs: Any) -> None: ...

class GroupBy(_GroupBy):
    def any(self, skipna: bool=...) -> Any: ...
    def all(self, skipna: bool=...) -> Any: ...
    def count(self) -> None: ...
    def mean(self, *args: Any, **kwargs: Any) -> Any: ...
    def median(self, **kwargs: Any) -> Any: ...
    def std(self, ddof: int=..., *args: Any, **kwargs: Any) -> Any: ...
    def var(self, ddof: int=..., *args: Any, **kwargs: Any) -> Any: ...
    def sem(self, ddof: int=...) -> Any: ...
    def size(self) -> Any: ...
    def ohlc(self) -> DataFrame: ...
    def describe(self, **kwargs: Any) -> Any: ...
    def resample(self, rule: Any, *args: Any, **kwargs: Any) -> Any: ...
    def rolling(self, *args: Any, **kwargs: Any) -> Any: ...
    def expanding(self, *args: Any, **kwargs: Any) -> Any: ...
    def pad(self, limit: Optional[Any] = ...) -> Any: ...
    ffill: Any = ...
    def backfill(self, limit: Optional[Any] = ...) -> Any: ...
    bfill: Any = ...
    def nth(self, n: Union[int, List[int]], dropna: Optional[str]=...) -> DataFrame: ...
    def quantile(self, q: Any = ..., interpolation: str=...) -> Any: ...
    def ngroup(self, ascending: bool=...) -> Any: ...
    def cumcount(self, ascending: bool=...) -> Any: ...
    def rank(self, method: str=..., ascending: bool=..., na_option: str=..., pct: bool=..., axis: int=...) -> Any: ...
    def cumprod(self, axis: int = ..., *args: Any, **kwargs: Any) -> Any: ...
    def cumsum(self, axis: int = ..., *args: Any, **kwargs: Any) -> Any: ...
    def cummin(self, axis: int = ..., **kwargs: Any) -> Any: ...
    def cummax(self, axis: int = ..., **kwargs: Any) -> Any: ...
    def shift(self, periods: int = ..., freq: Optional[Any] = ..., axis: int = ..., fill_value: Optional[Any] = ...) -> Any: ...
    def pct_change(self, periods: int = ..., fill_method: str = ..., limit: Optional[Any] = ..., freq: Optional[Any] = ..., axis: int = ...) -> Any: ...
    def head(self, n: int = ...) -> Any: ...
    def tail(self, n: int = ...) -> Any: ...

def get_groupby(obj: NDFrame, by: Optional[_KeysArgType]=..., axis: int=..., level: Any = ..., grouper: Optional[ops.BaseGrouper]=..., exclusions: Any = ..., selection: Any = ..., as_index: bool=..., sort: bool=..., group_keys: bool=..., squeeze: bool=..., observed: bool=..., mutated: bool=...) -> GroupBy: ...
