Repository: scipy/scipy
Pull request: MAINT: stats.mode: fix bug with `axis!=1`, `nan_policy='omit'`, `keepdims=False`
#### Reference issue
Closes gh-16952

#### What does this implement/fix?
gh-16952 reported a bug with `stats.mode` with `axis!=`, `nan_policy='omit'`, and `keepdims=False`. This fixes the bug.


Problem statement:
BUG: error from `scipy.stats.mode` with `NaN`s, `axis != 0`, `keepdims=False`, and `nan_policy="omit"`
### Describe your issue.

`scipy.stats.mode` raises an error when called with a particular combination of arguments:

* multidimensional `a` that has one or more `NaN` values
* `axis` is not `0`
* `keepdims=False`
* `nan_policy="omit"`

The error seems to be specific to this combination.

### Reproducing Code Example

```python
import numpy as np
import scipy.stats

data = np.ones((4, 3))
data[0, 0] = np.nan

result = scipy.stats.mode(
    a=data,
    axis=1,
    keepdims=False,
    nan_policy="omit",
)
```


### Error message

```shell
Traceback (most recent call last):
  File "/home/damien/venv_study/scipy/bug.py", line 12, in <module>
    result = scipy.stats.mode(
  File "/home/damien/venv_study/scipy/scipy/build-install/lib/python3.9/site-packages/scipy/stats/_stats_py.py", line 618, in mode
    return mstats_basic._mode(a, axis, keepdims=keepdims)
  File "/home/damien/venv_study/scipy/scipy/build-install/lib/python3.9/site-packages/scipy/stats/_mstats_basic.py", line 352, in _mode
    return ModeResult(*output)
TypeError: <lambda>() takes 3 positional arguments but 5 were given
```


### SciPy/NumPy/Python version information

1.10.0.dev0+1772.07fc190 1.23.2 sys.version_info(major=3, minor=9, micro=13, releaselevel='final', serial=0)

Hints from issue discussion:

Commit message: MAINT: stats.mode: fix bug with axis!=1, nan_policy='omit', keepdims=False

Patch to review:
diff --git a/scipy/stats/_mstats_basic.py b/scipy/stats/_mstats_basic.py
index 069983485b4e..e912a8a29688 100644
--- a/scipy/stats/_mstats_basic.py
+++ b/scipy/stats/_mstats_basic.py
@@ -340,6 +340,7 @@ def _mode1D(a):
     else:
         output = ma.apply_along_axis(_mode1D, axis, a)
         if keepdims is None or keepdims:
+            np.moveaxis(a, -1, axis)
             newshape = list(a.shape)
             newshape[axis] = 1
             slices = [slice(None)] * output.ndim
@@ -348,6 +349,8 @@ def _mode1D(a):
             slices[axis] = 1
             counts = output[tuple(slices)].reshape(newshape)
             output = (modes, counts)
+        else:
+            output = np.moveaxis(output, axis, 0)
 
     return ModeResult(*output)
 
diff --git a/scipy/stats/tests/test_stats.py b/scipy/stats/tests/test_stats.py
index 375d25a02da3..6523696ea126 100644
--- a/scipy/stats/tests/test_stats.py
+++ b/scipy/stats/tests/test_stats.py
@@ -2363,15 +2363,16 @@ def test_keepdims(self):
 
         # test nan_policy='omit'
         a = [[1, np.nan, np.nan, np.nan, 1],
-             [np.nan, np.nan, np.nan, np.nan, 2]]
+             [np.nan, np.nan, np.nan, np.nan, 2],
+             [1, 2, np.nan, 5, 5]]
 
         res = stats.mode(a, axis=1, keepdims=False, nan_policy='omit')
-        assert_array_equal(res.mode, [1, 2])
-        assert_array_equal(res.count, [2, 1])
+        assert_array_equal(res.mode, [1, 2, 5])
+        assert_array_equal(res.count, [2, 1, 2])
 
         res = stats.mode(a, axis=1, keepdims=True, nan_policy='omit')
-        assert_array_equal(res.mode, [[1], [2]])
-        assert_array_equal(res.count, [[2], [1]])
+        assert_array_equal(res.mode, [[1], [2], [5]])
+        assert_array_equal(res.count, [[2], [1], [2]])
 
         a = np.array(a)
         res = stats.mode(a, axis=None, keepdims=False, nan_policy='omit')
@@ -2384,6 +2385,15 @@ def test_keepdims(self):
         assert_array_equal(res, ref)
         assert res.mode.shape == ref.mode.shape == (1,)
 
+    def test_gh16952(self):
+        # Check that bug reported in gh-16952 is resolved
+        shape = (4, 3)
+        data = np.ones(shape)
+        data[0, 0] = np.nan
+        res = stats.mode(a=data, axis=1, keepdims=False, nan_policy="omit")
+        assert_array_equal(res.mode, [1, 1, 1, 1])
+        assert_array_equal(res.count, [2, 3, 3, 3])
+
 
 def test_mode_futurewarning():
     a = [1, 2, 5, 3, 5]


Code review comments:
diff_hunk: @@ -340,6 +340,7 @@ def _mode1D(a):
     else:
         output = ma.apply_along_axis(_mode1D, axis, a)
         if keepdims is None or keepdims:
+            np.moveaxis(a, -1, axis)
path: scipy/stats/_mstats_basic.py
text: @author:
```suggestion
```