Repository: Zeroto521/my-data-toolkit

Issue:
DEP: Drop `axis` option of `filter_in`
<!--
Thanks for contributing a pull request!

Please follow these standard acronyms to start the commit message:

- ENH: enhancement
- BUG: bug fix
- DOC: documentation
- TYP: type annotations
- TST: addition or modification of tests
- MAINT: maintenance commit (refactoring, typos, etc.)
- BLD: change related to building
- REL: related to releasing
- API: an (incompatible) API change
- DEP: deprecate something, or remove a deprecated object
- DEV: development tool or utility
- REV: revert an earlier commit
- PERF: performance improvement
- BOT: always commit via a bot
- CI: related to CI or CD
- CLN: Code cleanup
-->

- [ ] closes #xxxx
- [x] whatsnew entry

`axis` and `isin` functions could easily replace by `.T`.


Discussion:

Resolving patch:
diff --git a/dtoolkit/accessor/_util.py b/dtoolkit/accessor/_util.py
--- a/dtoolkit/accessor/_util.py
+++ b/dtoolkit/accessor/_util.py
@@ -3,14 +3,11 @@
 from typing import TYPE_CHECKING
 
 import numpy as np
-import pandas as pd
 
 if TYPE_CHECKING:
     from typing import Iterable
 
-    from dtoolkit._typing import IntOrStr
     from dtoolkit._typing import OneDimArray
-    from dtoolkit._typing import SeriesOrFrame
     from dtoolkit._typing import TwoDimArray
 
 
@@ -38,27 +35,6 @@ def get_mask(how: str, mask: TwoDimArray, axis: int) -> OneDimArray:
     raise TypeError("must specify how")
 
 
-def isin(
-    df: pd.DataFrame,
-    values: Iterable | SeriesOrFrame | dict[str, list[str]],
-    axis: IntOrStr = 0,
-) -> pd.DataFrame:
-    """
-    Extend :meth:`~pandas.DataFrame.isin` function. When ``values`` is
-    :obj:`dict` and ``axis`` is 1, ``values``' key could be index name.
-    """
-    from collections import defaultdict
-
-    axis = df._get_axis_number(axis)
-
-    if isinstance(values, dict) and axis == 1:
-        values = defaultdict(list, values)
-        result = (df.iloc[[r]].isin(values[i]) for r, i in enumerate(df.index))
-        return pd.concat(result, axis=0)
-
-    return df.isin(values)
-
-
 # based on more_itertools/more.py
 def collapse(iterable: Iterable):
     def walk(node):
diff --git a/dtoolkit/accessor/dataframe/filter_in.py b/dtoolkit/accessor/dataframe/filter_in.py
--- a/dtoolkit/accessor/dataframe/filter_in.py
+++ b/dtoolkit/accessor/dataframe/filter_in.py
@@ -5,30 +5,17 @@
 import pandas as pd
 
 from dtoolkit.accessor._util import get_mask
-from dtoolkit.accessor._util import isin
 from dtoolkit.accessor.register import register_dataframe_method
-from dtoolkit.util._decorator import deprecated_kwargs
 
 
 if TYPE_CHECKING:
     from typing import Iterable
 
-    from dtoolkit._typing import IntOrStr
-
 
 @register_dataframe_method
-@deprecated_kwargs(
-    "axis",
-    message=(
-        "The keyword argument '{argument}' of '{func_name}' is deprecated and will "
-        "be removed in 0.0.16. If want to filter columns please use '.T' firstly. "
-        "(Warning added DToolKit 0.0.15)"
-    ),
-)
 def filter_in(
     df: pd.DataFrame,
     condition: Iterable | pd.Series | pd.DataFrame | dict[str, list[str]],
-    axis: IntOrStr = 0,
     how: str = "all",
 ) -> pd.DataFrame:
     """
@@ -40,37 +27,26 @@ def filter_in(
     Parameters
     ----------
     condition : iterable, Series, DataFrame or dict
-        The result will only be true at a location if all the labels match.
-
-        * If ``condition`` is a :obj:`dict`, the keys must be the row/column
-          names, which must match. And ``how`` only works on these gave keys.
+        The filtered result is based on this specific condition.
 
-            - ``axis`` is 0 or 'index', keys would be recognize as column
-              names.
-            - ``axis`` is 1 or 'columns', keys would be recognize as index
-              names.
+        * If ``condition`` is a :obj:`dict`, the keys must be the column
+          names, which must be matched. And ``how`` only works on these gave keys.
 
         * If ``condition`` is a :obj:`~pandas.Series`, that's the index.
 
         * If ``condition`` is a :obj:`~pandas.DataFrame`, then both the index
-          and column labels must match.
-
-    axis : {0 or 'index', 1 or 'columns'}, default 0
-        Determine if rows or columns which contain value are filtered.
-
-        * 0, or 'index' : Filter rows which contain value.
-        * 1, or 'columns' : Filter columns which contain value.
+          and column labels must be matched.
 
         .. deprecated:: 0.0.15
             The ``axis`` is deprecated and will be removed in 0.0.16. If want to
             filter columns please use ``.T`` firstly. (Warning added DToolKit 0.0.15)
 
     how : {'any', 'all'}, default 'all'
-        Determine if row or column is filtered from :obj:`~pandas.DataFrame`,
-        when we have at least one value or all value.
+        Determine whether the row is filtered from :obj:`~pandas.DataFrame`,
+        when there have at least one value or all value.
 
-        * 'any' : If any values are present, filter that row or column.
-        * 'all' : If all values are present, filter that row or column.
+        * 'any' : If any values are present, filter that rows.
+        * 'all' : If all values are present, filter that rows.
 
     Returns
     -------
@@ -113,34 +89,27 @@ def filter_in(
 
     Filter columns.
 
-    >>> df.filter_in([0, 2], axis=1)
-                num_wings
-    falcon          2
-    dog             0
-    cat             0
+    >>> df.T.filter_in([0, 2])
+               falcon  dog  cat
+    num_wings       2    0    0
 
     When ``condition`` is a :obj:`dict`, we can pass values to check for each
-    row/column (depend on ``axis``) separately.
-
-    Filter rows, to check under the column (key) whether contains the value.
+    column separately.
 
     >>> df.filter_in({'num_legs': [2], 'num_wings': [2]})
             num_legs  num_wings
     falcon         2          2
 
-    Filter columns, to check under the index (key) whether contains the value.
-
-    >>> df.filter_in({'cat': [2]}, axis=1)
-            num_legs
-    falcon         2
-    dog            4
-    cat            2
-
     When ``values`` is a Series or DataFrame the index and column must match.
     Note that 'spider' doesn't match based on the number of legs in ``other``.
 
-    >>> other = pd.DataFrame({'num_legs': [8, 2], 'num_wings': [0, 2]},
-    ...                      index=['spider', 'falcon'])
+    >>> other = pd.DataFrame(
+    ...     {
+    ...         'num_legs': [8, 2],
+    ...         'num_wings': [0, 2],
+    ...     },
+    ...     index=['spider', 'falcon'],
+    ... )
     >>> other
             num_legs  num_wings
     spider         8          0
@@ -150,14 +119,10 @@ def filter_in(
     falcon         2          2
     """
 
-    axis = df._get_axis_number(axis)
-    another_axis = 1 - axis
-
-    mask = isin(df, condition, axis)
+    mask = df.isin(condition)
     if isinstance(condition, dict):
         # 'how' only works on condition's keys
-        names = condition.keys()
-        mask = mask[names] if axis == 0 else mask.loc[names]
-    mask = get_mask(how, mask, another_axis)
+        mask = mask[condition.keys()]
 
-    return df.loc(axis=axis)[mask]
+    mask = get_mask(how, mask, 1)
+    return df[mask]
diff --git a/dtoolkit/transformer/pandas.py b/dtoolkit/transformer/pandas.py
--- a/dtoolkit/transformer/pandas.py
+++ b/dtoolkit/transformer/pandas.py
@@ -363,12 +363,10 @@ class FilterInTF(DataFrameTF):
 
     Filter columns.
 
-    >>> tf = FilterInTF([0, 2], axis=1)
-    >>> tf.transform(df)
-    falcon    2
-    dog       0
-    cat       0
-    Name: num_wings, dtype: int64
+    >>> tf = FilterInTF([0, 2])
+    >>> tf.transform(df.T)
+               falcon  dog  cat
+    num_wings       2    0    0
 
     When ``condition`` is a :obj:`dict`, we can pass values to check for each
     column separately:


Test patch: