Repository: pandas-dev/pandas

Issue:
DEPR: DataFrame.groupby(axis=1)
It isn't obvious to me what you can do with `df.groupby(axis=1)` that you can't do with `df.T.groupby(axis=0)`.  In many cases we do the transpose under the hood anyway, so it isn't saving much/anything perf-wise.



Discussion:
There are only two benefits I see with keeping the `axis` argument.

 1. Wrapping the operation with transpose may be described as a clever trick that is likely not apparent to new users.
 2. dtypes aren't coerced to object (I'd guess they are coerced to object internally and then fixed, but I haven't checked)

For 1, this can at least partially be mitigated by adding a section to the User Guide. For 2, users can call `infer_objects`, although they may not realize the coercion happened.

I don't think either of these justify keeping the `axis` argument. I'm +1 on deprecating.
I don’t understand why we would remove the axis keyword from the `groupby` method.
I’m personally using code that groups columns using this option.
Sure, we can transpose, group by the index and transpose again but this is not convenient for the user.
Besides, I fail to see why groupby would be different from the many other methods that have an axis option. Why for instance would we remove it from `groupby` while keeping it in `sum`?

> Besides, I fail to see why groupby would be different from the many other methods that have an axis option. Why for instance would we remove it from groupby while keeping it in sum?

The main difference is maintenance burden.  DataFrame.sum(axis=1) is pretty simple, the cause of few bugs, and easy to debug when one is found.  DataFrameGroupBy with axis=1 is the opposite.
@DeaMariaLeon - how often do you find yourself using `axis=1` in groupby? Could you share an example, or some examples? In particular, it'd be good to know how the groups are determined (a list?), the number of groups, and what operations you find useful applying to them.
@rhshadrach here is an example. 

It is quite a common need to group by axis=1 when analyzing coorporate financial data. I used to have this: column names as months, rows were the different type of costs. Then I needed to find total costs by quarters and/or years. 

This example is a bit different: 
[groupby example.pdf](https://github.com/pandas-dev/pandas/files/10714573/groupby.example.pdf)


Patch:
diff --git a/doc/source/user_guide/categorical.rst b/doc/source/user_guide/categorical.rst
index 1bd20b54242e6..0b2224fe9bb32 100644
--- a/doc/source/user_guide/categorical.rst
+++ b/doc/source/user_guide/categorical.rst
@@ -617,8 +617,8 @@ even if some categories are not present in the data:
     df = pd.DataFrame(
         data=[[1, 2, 3], [4, 5, 6]],
         columns=pd.MultiIndex.from_arrays([["A", "B", "B"], columns]),
-    )
-    df.groupby(axis=1, level=1).sum()
+    ).T
+    df.groupby(level=1).sum()
 
 Groupby will also show "unused" categories:
 
diff --git a/doc/source/user_guide/groupby.rst b/doc/source/user_guide/groupby.rst
index 15baedbac31ba..b5bf7ee25a50f 100644
--- a/doc/source/user_guide/groupby.rst
+++ b/doc/source/user_guide/groupby.rst
@@ -94,15 +94,13 @@ object (more on what the GroupBy object is later), you may do the following:
     )
     speeds
 
-    # default is axis=0
     grouped = speeds.groupby("class")
-    grouped = speeds.groupby("order", axis="columns")
     grouped = speeds.groupby(["class", "order"])
 
 The mapping can be specified many different ways:
 
 * A Python function, to be called on each of the axis labels.
-* A list or NumPy array of the same length as the selected axis.
+* A list or NumPy array of the same length as the index.
 * A dict or ``Series``, providing a ``label -> group name`` mapping.
 * For ``DataFrame`` objects, a string indicating either a column name or
   an index level name to be used to group.
@@ -147,8 +145,8 @@ but the specified columns
    grouped = df2.groupby(level=df2.index.names.difference(["B"]))
    grouped.sum()
 
-These will split the DataFrame on its index (rows). We could also split by the
-columns:
+These will split the DataFrame on its index (rows). To split by columns, first do
+a tranpose:
 
 .. ipython::
 
@@ -159,7 +157,7 @@ columns:
        ...:         return 'consonant'
        ...:
 
-    In [5]: grouped = df.groupby(get_letter_type, axis=1)
+    In [5]: grouped = df.T.groupby(get_letter_type)
 
 pandas :class:`~pandas.Index` objects support duplicate values. If a
 non-unique index is used as the group key in a groupby operation, all values
@@ -254,7 +252,7 @@ above example we have:
 .. ipython:: python
 
    df.groupby("A").groups
-   df.groupby(get_letter_type, axis=1).groups
+   df.T.groupby(get_letter_type).groups
 
 Calling the standard Python ``len`` function on the GroupBy object just returns
 the length of the ``groups`` dict, so it is largely just a convenience:
@@ -496,7 +494,7 @@ An obvious one is aggregation via the
    grouped.aggregate(np.sum)
 
 As you can see, the result of the aggregation will have the group names as the
-new index along the grouped axis. In the case of multiple keys, the result is a
+new index. In the case of multiple keys, the result is a
 :ref:`MultiIndex <advanced.hierarchical>` by default, though this can be
 changed by using the ``as_index`` option:
 
@@ -1556,7 +1554,8 @@ Regroup columns of a DataFrame according to their sum, and sum the aggregated on
 
    df = pd.DataFrame({"a": [1, 0, 0], "b": [0, 1, 0], "c": [1, 0, 0], "d": [2, 3, 4]})
    df
-   df.groupby(df.sum(), axis=1).sum()
+   dft = df.T
+   dft.groupby(dft.sum()).sum()
 
 .. _groupby.multicolumn_factorization:
 
diff --git a/doc/source/user_guide/reshaping.rst b/doc/source/user_guide/reshaping.rst
index 1b8fdc75d5e88..6a34998ccd0a6 100644
--- a/doc/source/user_guide/reshaping.rst
+++ b/doc/source/user_guide/reshaping.rst
@@ -350,7 +350,7 @@ some very expressive and fast data manipulations.
    df.stack().mean(1).unstack()
 
    # same result, another way
-   df.groupby(level=1, axis=1).mean()
+   df.T.groupby(level=1).mean()
 
    df.stack().groupby(level=1).mean()
 
diff --git a/doc/source/whatsnew/v2.1.0.rst b/doc/source/whatsnew/v2.1.0.rst
index 2ac20e97409e7..475ca7551f049 100644
--- a/doc/source/whatsnew/v2.1.0.rst
+++ b/doc/source/whatsnew/v2.1.0.rst
@@ -93,6 +93,7 @@ Other API changes
 Deprecations
 ~~~~~~~~~~~~
 - Deprecating pinning ``group.name`` to each group in :meth:`SeriesGroupBy.aggregate` aggregations; if your operation requires utilizing the groupby keys, iterate over the groupby object instead (:issue:`41090`)
+- Deprecated ``axis=1`` in :meth:`DataFrame.groupby` and in :class:`Grouper` constructor, do ``frame.T.groupby(...)`` instead (:issue:`51203`)
 - Deprecated passing a :class:`DataFrame` to :meth:`DataFrame.from_records`, use :meth:`DataFrame.set_index` or :meth:`DataFrame.drop` instead (:issue:`51353`)
 - Deprecated accepting slices in :meth:`DataFrame.take`, call ``obj[slicer]`` or pass a sequence of integers instead (:issue:`51539`)
 -
diff --git a/pandas/core/frame.py b/pandas/core/frame.py
index aa3b10df742a2..8cd0ffadcc17c 100644
--- a/pandas/core/frame.py
+++ b/pandas/core/frame.py
@@ -8247,7 +8247,7 @@ def update(
     def groupby(
         self,
         by=None,
-        axis: Axis = 0,
+        axis: Axis | lib.NoDefault = no_default,
         level: IndexLabel | None = None,
         as_index: bool = True,
         sort: bool = True,
@@ -8255,11 +8255,29 @@ def groupby(
         observed: bool = False,
         dropna: bool = True,
     ) -> DataFrameGroupBy:
+        if axis is not lib.no_default:
+            axis = self._get_axis_number(axis)
+            if axis == 1:
+                warnings.warn(
+                    "DataFrame.groupby with axis=1 is deprecated. Do "
+                    "`frame.T.groupby(...)` without axis instead.",
+                    FutureWarning,
+                    stacklevel=find_stack_level(),
+                )
+            else:
+                warnings.warn(
+                    "The 'axis' keyword in DataFrame.groupby is deprecated and "
+                    "will be removed in a future version.",
+                    FutureWarning,
+                    stacklevel=find_stack_level(),
+                )
+        else:
+            axis = 0
+
         from pandas.core.groupby.generic import DataFrameGroupBy
 
         if level is None and by is None:
             raise TypeError("You have to supply one of 'by' and 'level'")
-        axis = self._get_axis_number(axis)
 
         return DataFrameGroupBy(
             obj=self,
diff --git a/pandas/core/groupby/generic.py b/pandas/core/groupby/generic.py
index dca2d5676f71d..1b8f08da07ea5 100644
--- a/pandas/core/groupby/generic.py
+++ b/pandas/core/groupby/generic.py
@@ -2238,6 +2238,10 @@ def fillna(
             the same results as :meth:`.DataFrame.fillna`. When the
             :class:`DataFrameGroupBy` ``axis`` argument is ``1``, using ``axis=0``
             or ``axis=1`` here will produce the same results.
+
+            .. deprecated:: 2.0.0
+                Use frame.T.groupby(...) instead.
+
         inplace : bool, default False
             Broken. Do not set to True.
         limit : int, default None
@@ -2300,7 +2304,7 @@ def fillna(
 
         Propagate non-null values forward or backward within each group along rows.
 
-        >>> df.groupby([0, 0, 1, 1], axis=1).fillna(method="ffill")
+        >>> df.T.groupby(np.array([0, 0, 1, 1])).fillna(method="ffill").T
            key    A    B    C
         0  0.0  0.0  2.0  2.0
         1  0.0  2.0  3.0  3.0
@@ -2308,7 +2312,7 @@ def fillna(
         3  1.0  3.0  NaN  NaN
         4  1.0  1.0  NaN  NaN
 
-        >>> df.groupby([0, 0, 1, 1], axis=1).fillna(method="bfill")
+        >>> df.T.groupby(np.array([0, 0, 1, 1])).fillna(method="bfill").T
            key    A    B    C
         0  0.0  NaN  2.0  NaN
         1  0.0  2.0  3.0  NaN
diff --git a/pandas/core/groupby/groupby.py b/pandas/core/groupby/groupby.py
index 55e14bc11246b..457352564f255 100644
--- a/pandas/core/groupby/groupby.py
+++ b/pandas/core/groupby/groupby.py
@@ -3071,9 +3071,10 @@ def _nth(
                 sort=self.sort,
             )
 
-        grb = dropped.groupby(
-            grouper, as_index=self.as_index, sort=self.sort, axis=self.axis
-        )
+        if self.axis == 1:
+            grb = dropped.T.groupby(grouper, as_index=self.as_index, sort=self.sort)
+        else:
+            grb = dropped.groupby(grouper, as_index=self.as_index, sort=self.sort)
         return grb.nth(n)
 
     @final
@@ -3882,10 +3883,13 @@ def pct_change(
             fill_method = "ffill"
             limit = 0
         filled = getattr(self, fill_method)(limit=limit)
-        fill_grp = filled.groupby(
-            self.grouper.codes, axis=self.axis, group_keys=self.group_keys
-        )
-        shifted = fill_grp.shift(periods=periods, freq=freq, axis=self.axis)
+        if self.axis == 0:
+            fill_grp = filled.groupby(self.grouper.codes, group_keys=self.group_keys)
+        else:
+            fill_grp = filled.T.groupby(self.grouper.codes, group_keys=self.group_keys)
+        shifted = fill_grp.shift(periods=periods, freq=freq)
+        if self.axis == 1:
+            shifted = shifted.T
         return (filled / shifted) - 1
 
     @final
diff --git a/pandas/core/groupby/grouper.py b/pandas/core/groupby/grouper.py
index f735ce682fc83..47d34e39bda6b 100644
--- a/pandas/core/groupby/grouper.py
+++ b/pandas/core/groupby/grouper.py
@@ -16,6 +16,7 @@
 
 from pandas._config import using_copy_on_write
 
+from pandas._libs import lib
 from pandas._typing import (
     ArrayLike,
     Axis,
@@ -258,10 +259,25 @@ def __init__(
         key=None,
         level=None,
         freq=None,
-        axis: Axis = 0,
+        axis: Axis | lib.NoDefault = lib.no_default,
         sort: bool = False,
         dropna: bool = True,
     ) -> None:
+        if type(self) is Grouper:
+            # i.e. not TimeGrouper
+            if axis is not lib.no_default:
+                warnings.warn(
+                    "Grouper axis keyword is deprecated and will be removed in a "
+                    "future version. To group on axis=1, use obj.T.groupby(...) "
+                    "instead",
+                    FutureWarning,
+                    stacklevel=find_stack_level(),
+                )
+            else:
+                axis = 0
+        if axis is lib.no_default:
+            axis = 0
+
         self.key = key
         self.level = level
         self.freq = freq
diff --git a/pandas/core/resample.py b/pandas/core/resample.py
index f23256c64db2d..665e32829a57e 100644
--- a/pandas/core/resample.py
+++ b/pandas/core/resample.py
@@ -1294,7 +1294,11 @@ def _downsample(self, how, **kwargs):
 
         # we are downsampling
         # we want to call the actual grouper method here
-        result = obj.groupby(self.grouper, axis=self.axis).aggregate(how, **kwargs)
+        if self.axis == 0:
+            result = obj.groupby(self.grouper).aggregate(how, **kwargs)
+        else:
+            # test_resample_axis1
+            result = obj.T.groupby(self.grouper).aggregate(how, **kwargs).T
 
         return self._wrap_result(result)
 
diff --git a/pandas/core/reshape/pivot.py b/pandas/core/reshape/pivot.py
index a919f72c7d220..5dd95d78c7b79 100644
--- a/pandas/core/reshape/pivot.py
+++ b/pandas/core/reshape/pivot.py
@@ -377,7 +377,8 @@ def _all_key(key):
             margin = data[rows + values].groupby(rows, observed=observed).agg(aggfunc)
             cat_axis = 1
 
-            for key, piece in table.groupby(level=0, axis=cat_axis, observed=observed):
+            for key, piece in table.T.groupby(level=0, observed=observed):
+                piece = piece.T
                 all_key = _all_key(key)
 
                 # we are going to mutate this, so need to copy!
@@ -390,7 +391,7 @@ def _all_key(key):
             from pandas import DataFrame
 
             cat_axis = 0
-            for key, piece in table.groupby(level=0, axis=cat_axis, observed=observed):
+            for key, piece in table.groupby(level=0, observed=observed):
                 if len(cols) > 1:
                     all_key = _all_key(key)
                 else:


Test patch:
diff --git a/pandas/tests/apply/test_str.py b/pandas/tests/apply/test_str.py
index 64f93e48b255c..64189fae5f578 100644
--- a/pandas/tests/apply/test_str.py
+++ b/pandas/tests/apply/test_str.py
@@ -268,9 +268,14 @@ def test_transform_groupby_kernel_frame(request, axis, float_frame, op):
     args = [0.0] if op == "fillna" else []
     if axis in (0, "index"):
         ones = np.ones(float_frame.shape[0])
+        msg = "The 'axis' keyword in DataFrame.groupby is deprecated"
     else:
         ones = np.ones(float_frame.shape[1])
-    expected = float_frame.groupby(ones, axis=axis).transform(op, *args)
+        msg = "DataFrame.groupby with axis=1 is deprecated"
+
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gb = float_frame.groupby(ones, axis=axis)
+    expected = gb.transform(op, *args)
     result = float_frame.transform(op, axis, *args)
     tm.assert_frame_equal(result, expected)
 
@@ -283,7 +288,9 @@ def test_transform_groupby_kernel_frame(request, axis, float_frame, op):
         ones = np.ones(float_frame.shape[0])
     else:
         ones = np.ones(float_frame.shape[1])
-    expected2 = float_frame.groupby(ones, axis=axis).transform(op, *args)
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gb2 = float_frame.groupby(ones, axis=axis)
+    expected2 = gb2.transform(op, *args)
     result2 = float_frame.transform(op, axis, *args)
     tm.assert_frame_equal(result2, expected2)
 
diff --git a/pandas/tests/groupby/aggregate/test_aggregate.py b/pandas/tests/groupby/aggregate/test_aggregate.py
index d658de4a7d7c3..14bd466b052bf 100644
--- a/pandas/tests/groupby/aggregate/test_aggregate.py
+++ b/pandas/tests/groupby/aggregate/test_aggregate.py
@@ -124,7 +124,9 @@ def test_groupby_aggregation_multi_level_column():
         columns=MultiIndex.from_tuples([("A", 0), ("A", 1), ("B", 0), ("B", 1)]),
     )
 
-    gb = df.groupby(level=1, axis=1)
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gb = df.groupby(level=1, axis=1)
     result = gb.sum(numeric_only=False)
     expected = DataFrame({0: [2.0, True, True, True], 1: [1, 0, 1, 1]})
 
@@ -253,7 +255,11 @@ def test_multiindex_groupby_mixed_cols_axis1(func, expected, dtype, result_dtype
         [[1, 2, 3, 4, 5, 6]] * 3,
         columns=MultiIndex.from_product([["a", "b"], ["i", "j", "k"]]),
     ).astype({("a", "j"): dtype, ("b", "j"): dtype})
-    result = df.groupby(level=1, axis=1).agg(func)
+
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gb = df.groupby(level=1, axis=1)
+    result = gb.agg(func)
     expected = DataFrame([expected] * 3, columns=["i", "j", "k"]).astype(
         result_dtype_dict
     )
@@ -278,7 +284,11 @@ def test_groupby_mixed_cols_axis1(func, expected_data, result_dtype_dict):
         columns=Index([10, 20, 10, 20], name="x"),
         dtype="int64",
     ).astype({10: "Int64"})
-    result = df.groupby("x", axis=1).agg(func)
+
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gb = df.groupby("x", axis=1)
+    result = gb.agg(func)
     expected = DataFrame(
         data=expected_data,
         index=Index([0, 1, 0], name="y"),
@@ -1447,7 +1457,9 @@ def test_groupby_complex_raises(func):
 def test_multi_axis_1_raises(func):
     # GH#46995
     df = DataFrame({"a": [1, 1, 2], "b": [3, 4, 5], "c": [6, 7, 8]})
-    gb = df.groupby("a", axis=1)
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gb = df.groupby("a", axis=1)
     with pytest.raises(NotImplementedError, match="axis other than 0 is not supported"):
         gb.agg(func)
 
diff --git a/pandas/tests/groupby/aggregate/test_cython.py b/pandas/tests/groupby/aggregate/test_cython.py
index 487daddd3d214..2fb7c8eb03bb0 100644
--- a/pandas/tests/groupby/aggregate/test_cython.py
+++ b/pandas/tests/groupby/aggregate/test_cython.py
@@ -122,10 +122,15 @@ def test_cython_agg_frame_columns():
     # #2113
     df = DataFrame({"x": [1, 2, 3], "y": [3, 4, 5]})
 
-    df.groupby(level=0, axis="columns").mean()
-    df.groupby(level=0, axis="columns").mean()
-    df.groupby(level=0, axis="columns").mean()
-    df.groupby(level=0, axis="columns").mean()
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        df.groupby(level=0, axis="columns").mean()
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        df.groupby(level=0, axis="columns").mean()
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        df.groupby(level=0, axis="columns").mean()
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        df.groupby(level=0, axis="columns").mean()
 
 
 def test_cython_agg_return_dict():
diff --git a/pandas/tests/groupby/test_allowlist.py b/pandas/tests/groupby/test_allowlist.py
index c7657d3e8eea5..bc9388075218e 100644
--- a/pandas/tests/groupby/test_allowlist.py
+++ b/pandas/tests/groupby/test_allowlist.py
@@ -76,11 +76,15 @@ def test_regression_allowlist_methods(raw_frame, op, axis, skipna, sort):
     # explicitly test the allowlist methods
     if axis == 0:
         frame = raw_frame
+        msg = "The 'axis' keyword in DataFrame.groupby is deprecated and will be"
     else:
         frame = raw_frame.T
+        msg = "DataFrame.groupby with axis=1 is deprecated"
 
-    if op in AGG_FUNCTIONS_WITH_SKIPNA:
+    with tm.assert_produces_warning(FutureWarning, match=msg):
         grouped = frame.groupby(level=0, axis=axis, sort=sort)
+
+    if op in AGG_FUNCTIONS_WITH_SKIPNA:
         result = getattr(grouped, op)(skipna=skipna)
         expected = frame.groupby(level=0).apply(
             lambda h: getattr(h, op)(axis=axis, skipna=skipna)
@@ -89,7 +93,6 @@ def test_regression_allowlist_methods(raw_frame, op, axis, skipna, sort):
             expected = expected.sort_index(axis=axis)
         tm.assert_frame_equal(result, expected)
     else:
-        grouped = frame.groupby(level=0, axis=axis, sort=sort)
         result = getattr(grouped, op)()
         expected = frame.groupby(level=0).apply(lambda h: getattr(h, op)(axis=axis))
         if sort:
diff --git a/pandas/tests/groupby/test_apply.py b/pandas/tests/groupby/test_apply.py
index 5fa7ed15a01d4..a7ba1e8e81848 100644
--- a/pandas/tests/groupby/test_apply.py
+++ b/pandas/tests/groupby/test_apply.py
@@ -68,9 +68,11 @@ def test_apply_trivial():
         columns=["key", "data"],
     )
     expected = pd.concat([df.iloc[1:], df.iloc[1:]], axis=1, keys=["float64", "object"])
-    result = df.groupby([str(x) for x in df.dtypes], axis=1).apply(
-        lambda x: df.iloc[1:]
-    )
+
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gb = df.groupby([str(x) for x in df.dtypes], axis=1)
+    result = gb.apply(lambda x: df.iloc[1:])
 
     tm.assert_frame_equal(result, expected)
 
@@ -82,9 +84,10 @@ def test_apply_trivial_fail():
         columns=["key", "data"],
     )
     expected = pd.concat([df, df], axis=1, keys=["float64", "object"])
-    result = df.groupby([str(x) for x in df.dtypes], axis=1, group_keys=True).apply(
-        lambda x: df
-    )
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gb = df.groupby([str(x) for x in df.dtypes], axis=1, group_keys=True)
+    result = gb.apply(lambda x: df)
 
     tm.assert_frame_equal(result, expected)
 
@@ -1102,10 +1105,15 @@ def test_apply_by_cols_equals_apply_by_rows_transposed():
         columns=MultiIndex.from_product([["A", "B"], [1, 2]]),
     )
 
-    by_rows = df.T.groupby(axis=0, level=0).apply(
-        lambda x: x.droplevel(axis=0, level=0)
-    )
-    by_cols = df.groupby(axis=1, level=0).apply(lambda x: x.droplevel(axis=1, level=0))
+    msg = "The 'axis' keyword in DataFrame.groupby is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gb = df.T.groupby(axis=0, level=0)
+    by_rows = gb.apply(lambda x: x.droplevel(axis=0, level=0))
+
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gb2 = df.groupby(axis=1, level=0)
+    by_cols = gb2.apply(lambda x: x.droplevel(axis=1, level=0))
 
     tm.assert_frame_equal(by_cols, by_rows.T)
     tm.assert_frame_equal(by_cols, df)
diff --git a/pandas/tests/groupby/test_apply_mutate.py b/pandas/tests/groupby/test_apply_mutate.py
index 6823aeef258cb..1df55abdc038d 100644
--- a/pandas/tests/groupby/test_apply_mutate.py
+++ b/pandas/tests/groupby/test_apply_mutate.py
@@ -112,7 +112,10 @@ def add_column(grouped):
         grouped["sum", name] = grouped.sum(axis=1)
         return grouped
 
-    result = df.groupby(level=1, axis=1).apply(add_column)
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gb = df.groupby(level=1, axis=1)
+    result = gb.apply(add_column)
     expected = pd.DataFrame(
         [
             [1, 1, 1, 3, 1, 1, 1, 3],
diff --git a/pandas/tests/groupby/test_categorical.py b/pandas/tests/groupby/test_categorical.py
index fa8df166d56ac..dbbfab14d5c76 100644
--- a/pandas/tests/groupby/test_categorical.py
+++ b/pandas/tests/groupby/test_categorical.py
@@ -1301,8 +1301,14 @@ def test_groupby_categorical_axis_1(code):
     # GH 13420
     df = DataFrame({"a": [1, 2, 3, 4], "b": [-1, -2, -3, -4], "c": [5, 6, 7, 8]})
     cat = Categorical.from_codes(code, categories=list("abc"))
-    result = df.groupby(cat, axis=1).mean()
-    expected = df.T.groupby(cat, axis=0).mean().T
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gb = df.groupby(cat, axis=1)
+    result = gb.mean()
+    msg = "The 'axis' keyword in DataFrame.groupby is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gb2 = df.T.groupby(cat, axis=0)
+    expected = gb2.mean().T
     tm.assert_frame_equal(result, expected)
 
 
diff --git a/pandas/tests/groupby/test_filters.py b/pandas/tests/groupby/test_filters.py
index f534a0c65fdbc..3f0150a2186a9 100644
--- a/pandas/tests/groupby/test_filters.py
+++ b/pandas/tests/groupby/test_filters.py
@@ -125,7 +125,11 @@ def test_filter_with_axis_in_groupby():
     # issue 11041
     index = pd.MultiIndex.from_product([range(10), [0, 1]])
     data = DataFrame(np.arange(100).reshape(-1, 20), columns=index, dtype="int64")
-    result = data.groupby(level=0, axis=1).filter(lambda x: x.iloc[0, 0] > 10)
+
+    msg = "DataFrame.groupby with axis=1"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gb = data.groupby(level=0, axis=1)
+    result = gb.filter(lambda x: x.iloc[0, 0] > 10)
     expected = data.iloc[:, 12:20]
     tm.assert_frame_equal(result, expected)
 
diff --git a/pandas/tests/groupby/test_function.py b/pandas/tests/groupby/test_function.py
index 535e8fa5b9354..e6709329f8f52 100644
--- a/pandas/tests/groupby/test_function.py
+++ b/pandas/tests/groupby/test_function.py
@@ -1135,7 +1135,9 @@ def test_frame_describe_multikey(tsframe):
     expected = pd.concat(desc_groups, axis=1)
     tm.assert_frame_equal(result, expected)
 
-    groupedT = tsframe.groupby({"A": 0, "B": 0, "C": 1, "D": 1}, axis=1)
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        groupedT = tsframe.groupby({"A": 0, "B": 0, "C": 1, "D": 1}, axis=1)
     result = groupedT.describe()
     expected = tsframe.describe().T
     # reverting the change from https://github.com/pandas-dev/pandas/pull/35441/
diff --git a/pandas/tests/groupby/test_groupby.py b/pandas/tests/groupby/test_groupby.py
index 97e88a8545aa5..4682d262bf300 100644
--- a/pandas/tests/groupby/test_groupby.py
+++ b/pandas/tests/groupby/test_groupby.py
@@ -447,7 +447,9 @@ def test_frame_groupby(tsframe):
 
 def test_frame_groupby_columns(tsframe):
     mapping = {"A": 0, "B": 0, "C": 1, "D": 1}
-    grouped = tsframe.groupby(mapping, axis=1)
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        grouped = tsframe.groupby(mapping, axis=1)
 
     # aggregate
     aggregated = grouped.aggregate(np.mean)
@@ -456,7 +458,9 @@ def test_frame_groupby_columns(tsframe):
 
     # transform
     tf = lambda x: x - x.mean()
-    groupedT = tsframe.T.groupby(mapping, axis=0)
+    msg = "The 'axis' keyword in DataFrame.groupby is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        groupedT = tsframe.T.groupby(mapping, axis=0)
     tm.assert_frame_equal(groupedT.transform(tf).T, grouped.transform(tf))
 
     # iterate
@@ -850,8 +854,10 @@ def test_groupby_as_index_corner(df, ts):
         ts.groupby(lambda x: x.weekday(), as_index=False)
 
     msg = "as_index=False only valid for axis=0"
+    depr_msg = "DataFrame.groupby with axis=1 is deprecated"
     with pytest.raises(ValueError, match=msg):
-        df.groupby(lambda x: x.lower(), as_index=False, axis=1)
+        with tm.assert_produces_warning(FutureWarning, match=depr_msg):
+            df.groupby(lambda x: x.lower(), as_index=False, axis=1)
 
 
 def test_groupby_multiple_key():
@@ -860,9 +866,11 @@ def test_groupby_multiple_key():
     agged = grouped.sum()
     tm.assert_almost_equal(df.values, agged.values)
 
-    grouped = df.T.groupby(
-        [lambda x: x.year, lambda x: x.month, lambda x: x.day], axis=1
-    )
+    depr_msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=depr_msg):
+        grouped = df.T.groupby(
+            [lambda x: x.year, lambda x: x.month, lambda x: x.day], axis=1
+        )
 
     agged = grouped.agg(lambda x: x.sum())
     tm.assert_index_equal(agged.index, df.columns)
@@ -901,7 +909,9 @@ def test_raises_on_nuisance(df):
         grouped.sum()
 
     # won't work with axis = 1
-    grouped = df.groupby({"A": 0, "C": 0, "D": 1, "E": 1}, axis=1)
+    depr_msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=depr_msg):
+        grouped = df.groupby({"A": 0, "C": 0, "D": 1, "E": 1}, axis=1)
     msg = "does not support reduction 'sum'"
     with pytest.raises(TypeError, match=msg):
         grouped.agg(lambda x: x.sum(0, numeric_only=False))
@@ -1146,7 +1156,10 @@ def test_groupby_with_hier_columns():
     result = df.groupby(level=0).mean()
     tm.assert_index_equal(result.columns, columns)
 
-    result = df.groupby(level=0, axis=1).mean()
+    depr_msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=depr_msg):
+        gb = df.groupby(level=0, axis=1)
+    result = gb.mean()
     tm.assert_index_equal(result.index, df.index)
 
     result = df.groupby(level=0).agg(np.mean)
@@ -1155,7 +1168,9 @@ def test_groupby_with_hier_columns():
     result = df.groupby(level=0).apply(lambda x: x.mean())
     tm.assert_index_equal(result.columns, columns)
 
-    result = df.groupby(level=0, axis=1).agg(lambda x: x.mean(1))
+    with tm.assert_produces_warning(FutureWarning, match=depr_msg):
+        gb = df.groupby(level=0, axis=1)
+    result = gb.agg(lambda x: x.mean(1))
     tm.assert_index_equal(result.columns, Index(["A", "B"]))
     tm.assert_index_equal(result.index, df.index)
 
@@ -2127,7 +2142,11 @@ def test_groupby_axis_1(group_name):
     df.index.name = "y"
     df.columns.name = "x"
 
-    results = df.groupby(group_name, axis=1).sum()
+    depr_msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=depr_msg):
+        gb = df.groupby(group_name, axis=1)
+
+    results = gb.sum()
     expected = df.T.groupby(group_name).sum().T
     tm.assert_frame_equal(results, expected)
 
@@ -2135,7 +2154,9 @@ def test_groupby_axis_1(group_name):
     iterables = [["bar", "baz", "foo"], ["one", "two"]]
     mi = MultiIndex.from_product(iterables=iterables, names=["x", "x1"])
     df = DataFrame(np.arange(18).reshape(3, 6), index=[0, 1, 0], columns=mi)
-    results = df.groupby(group_name, axis=1).sum()
+    with tm.assert_produces_warning(FutureWarning, match=depr_msg):
+        gb = df.groupby(group_name, axis=1)
+    results = gb.sum()
     expected = df.T.groupby(group_name).sum().T
     tm.assert_frame_equal(results, expected)
 
@@ -2288,8 +2309,12 @@ def test_groupby_crash_on_nunique(axis):
     axis_number = df._get_axis_number(axis)
     if not axis_number:
         df = df.T
+        msg = "The 'axis' keyword in DataFrame.groupby is deprecated"
+    else:
+        msg = "DataFrame.groupby with axis=1 is deprecated"
 
-    gb = df.groupby(axis=axis_number, level=0)
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gb = df.groupby(axis=axis_number, level=0)
     result = gb.nunique()
 
     expected = DataFrame({"A": [1, 2], "D": [1, 1]}, index=dti)
@@ -2301,11 +2326,13 @@ def test_groupby_crash_on_nunique(axis):
 
     if axis_number == 0:
         # same thing, but empty columns
-        gb2 = df[[]].groupby(axis=axis_number, level=0)
+        with tm.assert_produces_warning(FutureWarning, match=msg):
+            gb2 = df[[]].groupby(axis=axis_number, level=0)
         exp = expected[[]]
     else:
         # same thing, but empty rows
-        gb2 = df.loc[[]].groupby(axis=axis_number, level=0)
+        with tm.assert_produces_warning(FutureWarning, match=msg):
+            gb2 = df.loc[[]].groupby(axis=axis_number, level=0)
         # default for empty when we can't infer a dtype is float64
         exp = expected.loc[[]].astype(np.float64)
 
@@ -2385,7 +2412,10 @@ def test_subsetting_columns_keeps_attrs(klass, attr, value):
 
 def test_subsetting_columns_axis_1():
     # GH 37725
-    g = DataFrame({"A": [1], "B": [2], "C": [3]}).groupby([0, 0, 1], axis=1)
+    df = DataFrame({"A": [1], "B": [2], "C": [3]})
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        g = df.groupby([0, 0, 1], axis=1)
     match = "Cannot subset columns when using axis=1"
     with pytest.raises(ValueError, match=match):
         g[["A", "B"]].sum()
diff --git a/pandas/tests/groupby/test_grouping.py b/pandas/tests/groupby/test_grouping.py
index f5bbfce560d33..c3081069d9330 100644
--- a/pandas/tests/groupby/test_grouping.py
+++ b/pandas/tests/groupby/test_grouping.py
@@ -210,7 +210,10 @@ def test_grouper_creation_bug(self):
         result = g.sum()
         tm.assert_frame_equal(result, expected)
 
-        g = df.groupby(Grouper(key="A", axis=0))
+        msg = "Grouper axis keyword is deprecated and will be removed"
+        with tm.assert_produces_warning(FutureWarning, match=msg):
+            gpr = Grouper(key="A", axis=0)
+        g = df.groupby(gpr)
         result = g.sum()
         tm.assert_frame_equal(result, expected)
 
@@ -338,7 +341,9 @@ def test_groupby_categorical_index_and_columns(self, observed):
         )
         cat_columns = CategoricalIndex(columns, categories=categories, ordered=True)
         df = DataFrame(data=data, columns=cat_columns)
-        result = df.groupby(axis=1, level=0, observed=observed).sum()
+        depr_msg = "DataFrame.groupby with axis=1 is deprecated"
+        with tm.assert_produces_warning(FutureWarning, match=depr_msg):
+            result = df.groupby(axis=1, level=0, observed=observed).sum()
         expected_data = np.array([[4, 2], [4, 2], [4, 2], [4, 2], [4, 2]], int)
         expected_columns = CategoricalIndex(
             categories, categories=categories, ordered=True
@@ -348,7 +353,9 @@ def test_groupby_categorical_index_and_columns(self, observed):
 
         # test transposed version
         df = DataFrame(data.T, index=cat_columns)
-        result = df.groupby(axis=0, level=0, observed=observed).sum()
+        msg = "The 'axis' keyword in DataFrame.groupby is deprecated"
+        with tm.assert_produces_warning(FutureWarning, match=msg):
+            result = df.groupby(axis=0, level=0, observed=observed).sum()
         expected = DataFrame(data=expected_data.T, index=expected_columns)
         tm.assert_frame_equal(result, expected)
 
@@ -453,7 +460,10 @@ def test_multiindex_passthru(self):
         df = DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
         df.columns = MultiIndex.from_tuples([(0, 1), (1, 1), (2, 1)])
 
-        result = df.groupby(axis=1, level=[0, 1]).first()
+        depr_msg = "DataFrame.groupby with axis=1 is deprecated"
+        with tm.assert_produces_warning(FutureWarning, match=depr_msg):
+            gb = df.groupby(axis=1, level=[0, 1])
+        result = gb.first()
         tm.assert_frame_equal(result, df)
 
     def test_multiindex_negative_level(self, mframe):
@@ -559,9 +569,10 @@ def test_groupby_level(self, sort, mframe, df):
         tm.assert_frame_equal(result1, expected1)
 
         # axis=1
-
-        result0 = frame.T.groupby(level=0, axis=1, sort=sort).sum()
-        result1 = frame.T.groupby(level=1, axis=1, sort=sort).sum()
+        msg = "DataFrame.groupby with axis=1 is deprecated"
+        with tm.assert_produces_warning(FutureWarning, match=msg):
+            result0 = frame.T.groupby(level=0, axis=1, sort=sort).sum()
+            result1 = frame.T.groupby(level=1, axis=1, sort=sort).sum()
         tm.assert_frame_equal(result0, expected0.T)
         tm.assert_frame_equal(result1, expected1.T)
 
@@ -577,10 +588,15 @@ def test_groupby_level_index_names(self, axis):
         )
         if axis in (1, "columns"):
             df = df.T
-        df.groupby(level="exp", axis=axis)
+            depr_msg = "DataFrame.groupby with axis=1 is deprecated"
+        else:
+            depr_msg = "The 'axis' keyword in DataFrame.groupby is deprecated"
+        with tm.assert_produces_warning(FutureWarning, match=depr_msg):
+            df.groupby(level="exp", axis=axis)
         msg = f"level name foo is not the name of the {df._get_axis_name(axis)}"
         with pytest.raises(ValueError, match=msg):
-            df.groupby(level="foo", axis=axis)
+            with tm.assert_produces_warning(FutureWarning, match=depr_msg):
+                df.groupby(level="foo", axis=axis)
 
     @pytest.mark.parametrize("sort", [True, False])
     def test_groupby_level_with_nas(self, sort):
@@ -958,7 +974,9 @@ def test_multi_iter_frame(self, three_group):
 
         # axis = 1
         three_levels = three_group.groupby(["A", "B", "C"]).mean()
-        grouped = three_levels.T.groupby(axis=1, level=(1, 2))
+        depr_msg = "DataFrame.groupby with axis=1 is deprecated"
+        with tm.assert_produces_warning(FutureWarning, match=depr_msg):
+            grouped = three_levels.T.groupby(axis=1, level=(1, 2))
         for key, group in grouped:
             pass
 
diff --git a/pandas/tests/groupby/test_indexing.py b/pandas/tests/groupby/test_indexing.py
index 06b77c8f21e30..1c22da68499f8 100644
--- a/pandas/tests/groupby/test_indexing.py
+++ b/pandas/tests/groupby/test_indexing.py
@@ -281,7 +281,9 @@ def column_group_df():
 
 
 def test_column_axis(column_group_df):
-    g = column_group_df.groupby(column_group_df.iloc[1], axis=1)
+    msg = "DataFrame.groupby with axis=1"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        g = column_group_df.groupby(column_group_df.iloc[1], axis=1)
     result = g._positional_selector[1:-1]
     expected = column_group_df.iloc[:, [1, 3]]
 
diff --git a/pandas/tests/groupby/test_missing.py b/pandas/tests/groupby/test_missing.py
index 63772c24ca34b..d2939573fb994 100644
--- a/pandas/tests/groupby/test_missing.py
+++ b/pandas/tests/groupby/test_missing.py
@@ -94,8 +94,13 @@ def test_fill_consistency():
         np.nan,
     ]
 
-    expected = df.groupby(level=0, axis=0).fillna(method="ffill")
-    result = df.T.groupby(level=0, axis=1).fillna(method="ffill").T
+    msg = "The 'axis' keyword in DataFrame.groupby is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        expected = df.groupby(level=0, axis=0).fillna(method="ffill")
+
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        result = df.T.groupby(level=0, axis=1).fillna(method="ffill").T
     tm.assert_frame_equal(result, expected)
 
 
diff --git a/pandas/tests/groupby/test_nth.py b/pandas/tests/groupby/test_nth.py
index 874b37120cc23..61b20077cdcd0 100644
--- a/pandas/tests/groupby/test_nth.py
+++ b/pandas/tests/groupby/test_nth.py
@@ -534,7 +534,9 @@ def test_groupby_head_tail_axis_1(op, n, expected_cols):
     df = DataFrame(
         [[1, 2, 3], [1, 4, 5], [2, 6, 7], [3, 8, 9]], columns=["A", "B", "C"]
     )
-    g = df.groupby([0, 0, 1], axis=1)
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        g = df.groupby([0, 0, 1], axis=1)
     expected = df.iloc[:, expected_cols]
     result = getattr(g, op)(n)
     tm.assert_frame_equal(result, expected)
@@ -757,7 +759,10 @@ def test_groupby_nth_with_column_axis():
         index=["z", "y"],
         columns=["C", "B", "A"],
     )
-    result = df.groupby(df.iloc[1], axis=1).nth(0)
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gb = df.groupby(df.iloc[1], axis=1)
+    result = gb.nth(0)
     expected = df.iloc[:, [0, 2]]
     tm.assert_frame_equal(result, expected)
 
@@ -780,7 +785,9 @@ def test_nth_slices_with_column_axis(
     start, stop, expected_values, expected_columns, method
 ):
     df = DataFrame([range(5)], columns=[list("ABCDE")])
-    gb = df.groupby([5, 5, 5, 6, 6], axis=1)
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gb = df.groupby([5, 5, 5, 6, 6], axis=1)
     result = {
         "call": lambda start, stop: gb.nth(slice(start, stop)),
         "index": lambda start, stop: gb.nth[start:stop],
diff --git a/pandas/tests/groupby/test_quantile.py b/pandas/tests/groupby/test_quantile.py
index 79354e550d3f6..bc0422d41e74a 100644
--- a/pandas/tests/groupby/test_quantile.py
+++ b/pandas/tests/groupby/test_quantile.py
@@ -396,7 +396,10 @@ def test_columns_groupby_quantile():
         index=list("XYZ"),
         columns=pd.Series(list("ABAB"), name="col"),
     )
-    result = df.groupby("col", axis=1).quantile(q=[0.8, 0.2])
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gb = df.groupby("col", axis=1)
+    result = gb.quantile(q=[0.8, 0.2])
     expected = DataFrame(
         [
             [1.6, 0.4, 2.6, 1.4],
diff --git a/pandas/tests/groupby/test_raises.py b/pandas/tests/groupby/test_raises.py
index 0dd845bc35482..f29e2545cde14 100644
--- a/pandas/tests/groupby/test_raises.py
+++ b/pandas/tests/groupby/test_raises.py
@@ -13,6 +13,7 @@
     Grouper,
     Series,
 )
+import pandas._testing as tm
 from pandas.tests.groupby import get_groupby_method_args
 
 
@@ -628,6 +629,8 @@ def test_groupby_raises_category_on_category(
 def test_subsetting_columns_axis_1_raises():
     # GH 35443
     df = DataFrame({"a": [1], "b": [2], "c": [3]})
-    gb = df.groupby("a", axis=1)
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gb = df.groupby("a", axis=1)
     with pytest.raises(ValueError, match="Cannot subset columns when using axis=1"):
         gb["b"]
diff --git a/pandas/tests/groupby/test_rank.py b/pandas/tests/groupby/test_rank.py
index d0b848a567346..9f42f6ad72591 100644
--- a/pandas/tests/groupby/test_rank.py
+++ b/pandas/tests/groupby/test_rank.py
@@ -619,7 +619,9 @@ def test_rank_multiindex():
         axis=1,
     )
 
-    gb = df.groupby(level=0, axis=1)
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gb = df.groupby(level=0, axis=1)
     result = gb.rank(axis=1)
 
     expected = concat(
@@ -639,7 +641,9 @@ def test_groupby_axis0_rank_axis1():
         {0: [1, 3, 5, 7], 1: [2, 4, 6, 8], 2: [1.5, 3.5, 5.5, 7.5]},
         index=["a", "a", "b", "b"],
     )
-    gb = df.groupby(level=0, axis=0)
+    msg = "The 'axis' keyword in DataFrame.groupby is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gb = df.groupby(level=0, axis=0)
 
     res = gb.rank(axis=1)
 
@@ -661,7 +665,9 @@ def test_groupby_axis0_cummax_axis1():
         {0: [1, 3, 5, 7], 1: [2, 4, 6, 8], 2: [1.5, 3.5, 5.5, 7.5]},
         index=["a", "a", "b", "b"],
     )
-    gb = df.groupby(level=0, axis=0)
+    msg = "The 'axis' keyword in DataFrame.groupby is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gb = df.groupby(level=0, axis=0)
 
     cmax = gb.cummax(axis=1)
     expected = df[[0, 1]].astype(np.float64)
diff --git a/pandas/tests/groupby/test_size.py b/pandas/tests/groupby/test_size.py
index c0c98562eda68..e29f87992f8a1 100644
--- a/pandas/tests/groupby/test_size.py
+++ b/pandas/tests/groupby/test_size.py
@@ -39,7 +39,9 @@ def test_size_axis_1(df, axis_1, by, sort, dropna):
     if tm.is_integer_dtype(expected.index) and not any(x is None for x in by):
         expected.index = expected.index.astype(np.int_)
 
-    grouped = df.groupby(by=by, axis=axis_1, sort=sort, dropna=dropna)
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        grouped = df.groupby(by=by, axis=axis_1, sort=sort, dropna=dropna)
     result = grouped.size()
     tm.assert_series_equal(result, expected)
 
diff --git a/pandas/tests/groupby/test_value_counts.py b/pandas/tests/groupby/test_value_counts.py
index 2c3c2277ed627..5477ad75a56f7 100644
--- a/pandas/tests/groupby/test_value_counts.py
+++ b/pandas/tests/groupby/test_value_counts.py
@@ -233,7 +233,9 @@ def education_df():
 
 
 def test_axis(education_df):
-    gp = education_df.groupby("country", axis=1)
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gp = education_df.groupby("country", axis=1)
     with pytest.raises(NotImplementedError, match="axis"):
         gp.value_counts()
 
diff --git a/pandas/tests/groupby/transform/test_transform.py b/pandas/tests/groupby/transform/test_transform.py
index 8abcc52db0500..27ffeb9247556 100644
--- a/pandas/tests/groupby/transform/test_transform.py
+++ b/pandas/tests/groupby/transform/test_transform.py
@@ -149,7 +149,9 @@ def test_transform_broadcast(tsframe, ts):
             assert_fp_equal(res[col], agged[col])
 
     # group columns
-    grouped = tsframe.groupby({"A": 0, "B": 0, "C": 1, "D": 1}, axis=1)
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        grouped = tsframe.groupby({"A": 0, "B": 0, "C": 1, "D": 1}, axis=1)
     result = grouped.transform(np.mean)
     tm.assert_index_equal(result.index, tsframe.index)
     tm.assert_index_equal(result.columns, tsframe.columns)
@@ -165,7 +167,10 @@ def test_transform_axis_1(request, transformation_func):
 
     df = DataFrame({"a": [1, 2], "b": [3, 4], "c": [5, 6]}, index=["x", "y"])
     args = get_groupby_method_args(transformation_func, df)
-    result = df.groupby([0, 0, 1], axis=1).transform(transformation_func, *args)
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gb = df.groupby([0, 0, 1], axis=1)
+    result = gb.transform(transformation_func, *args)
     expected = df.T.groupby([0, 0, 1]).transform(transformation_func, *args).T
 
     if transformation_func in ["diff", "shift"]:
@@ -187,7 +192,11 @@ def test_transform_axis_1_reducer(request, reduction_func):
         request.node.add_marker(marker)
 
     df = DataFrame({"a": [1, 2], "b": [3, 4], "c": [5, 6]}, index=["x", "y"])
-    result = df.groupby([0, 0, 1], axis=1).transform(reduction_func)
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gb = df.groupby([0, 0, 1], axis=1)
+
+    result = gb.transform(reduction_func)
     expected = df.T.groupby([0, 0, 1]).transform(reduction_func).T
     tm.assert_equal(result, expected)
 
@@ -212,7 +221,9 @@ def test_transform_axis_ts(tsframe):
     tm.assert_frame_equal(result, expected)
 
     ts = ts.T
-    grouped = ts.groupby(lambda x: x.weekday(), axis=1, group_keys=False)
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        grouped = ts.groupby(lambda x: x.weekday(), axis=1, group_keys=False)
     result = ts - grouped.transform("mean")
     expected = grouped.apply(lambda x: (x.T - x.mean(1)).T)
     tm.assert_frame_equal(result, expected)
@@ -225,7 +236,9 @@ def test_transform_axis_ts(tsframe):
     tm.assert_frame_equal(result, expected)
 
     ts = ts.T
-    grouped = ts.groupby(lambda x: x.weekday(), axis=1, group_keys=False)
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        grouped = ts.groupby(lambda x: x.weekday(), axis=1, group_keys=False)
     result = ts - grouped.transform("mean")
     expected = grouped.apply(lambda x: (x.T - x.mean(1)).T)
     tm.assert_frame_equal(result, expected)
@@ -770,9 +783,12 @@ def test_transform_with_non_scalar_group():
         np.random.randint(1, 10, (4, 12)), columns=cols, index=["A", "C", "G", "T"]
     )
 
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        gb = df.groupby(axis=1, level=1)
     msg = "transform must return a scalar value for each group.*"
     with pytest.raises(ValueError, match=msg):
-        df.groupby(axis=1, level=1).transform(lambda z: z.div(z.sum(axis=1), axis=0))
+        gb.transform(lambda z: z.div(z.sum(axis=1), axis=0))
 
 
 @pytest.mark.parametrize(
diff --git a/pandas/tests/plotting/test_boxplot_method.py b/pandas/tests/plotting/test_boxplot_method.py
index 29276eba09346..c47a5a55dfcf6 100644
--- a/pandas/tests/plotting/test_boxplot_method.py
+++ b/pandas/tests/plotting/test_boxplot_method.py
@@ -351,7 +351,9 @@ def test_boxplot_legacy2(self):
     def test_boxplot_legacy3(self):
         tuples = zip(string.ascii_letters[:10], range(10))
         df = DataFrame(np.random.rand(10, 3), index=MultiIndex.from_tuples(tuples))
-        grouped = df.unstack(level=1).groupby(level=0, axis=1)
+        msg = "DataFrame.groupby with axis=1 is deprecated"
+        with tm.assert_produces_warning(FutureWarning, match=msg):
+            grouped = df.unstack(level=1).groupby(level=0, axis=1)
         with tm.assert_produces_warning(UserWarning, check_stacklevel=False):
             axes = _check_plot_works(grouped.boxplot, return_type="axes")
         self._check_axes_shape(list(axes.values), axes_num=3, layout=(2, 2))
diff --git a/pandas/tests/resample/test_datetime_index.py b/pandas/tests/resample/test_datetime_index.py
index d7ee7744ebcd4..ac262495ede3c 100644
--- a/pandas/tests/resample/test_datetime_index.py
+++ b/pandas/tests/resample/test_datetime_index.py
@@ -642,7 +642,9 @@ def test_resample_dup_index():
     )
     df.iloc[3, :] = np.nan
     result = df.resample("Q", axis=1).mean()
-    expected = df.groupby(lambda x: int((x.month - 1) / 3), axis=1).mean()
+    msg = "DataFrame.groupby with axis=1 is deprecated"
+    with tm.assert_produces_warning(FutureWarning, match=msg):
+        expected = df.groupby(lambda x: int((x.month - 1) / 3), axis=1).mean()
     expected.columns = [Period(year=2000, quarter=i + 1, freq="Q") for i in range(4)]
     tm.assert_frame_equal(result, expected)
 
diff --git a/pandas/tests/test_multilevel.py b/pandas/tests/test_multilevel.py
index 023411f486c6a..f8e1128042dbb 100644
--- a/pandas/tests/test_multilevel.py
+++ b/pandas/tests/test_multilevel.py
@@ -27,7 +27,11 @@ def test_reindex_level(self, multiindex_year_month_day_dataframe_random_data):
         tm.assert_series_equal(result, expected, check_names=False)
 
         # axis=1
-        month_sums = ymd.T.groupby("month", axis=1).sum()
+        msg = "DataFrame.groupby with axis=1 is deprecated"
+        with tm.assert_produces_warning(FutureWarning, match=msg):
+            gb = ymd.T.groupby("month", axis=1)
+
+        month_sums = gb.sum()
         result = month_sums.reindex(columns=ymd.index, level=1)
         expected = ymd.groupby(level="month").transform(np.sum).T
         tm.assert_frame_equal(result, expected)
@@ -96,7 +100,9 @@ def test_groupby_level_no_obs(self):
         df = DataFrame([[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]], columns=midx)
         df1 = df.loc(axis=1)[df.columns.map(lambda u: u[0] in ["f2", "f3"])]
 
-        grouped = df1.groupby(axis=1, level=0)
+        msg = "DataFrame.groupby with axis=1 is deprecated"
+        with tm.assert_produces_warning(FutureWarning, match=msg):
+            grouped = df1.groupby(axis=1, level=0)
         result = grouped.sum()
         assert (result.columns == ["f2", "f3"]).all()