From aa592864a214c804dd0856d23406a5f5fed1e93b Mon Sep 17 00:00:00 2001 From: Bill Little Date: Wed, 16 Jul 2025 17:08:05 +0100 Subject: [PATCH 1/3] support scalar cube to pandas dataframe --- lib/iris/pandas.py | 10 ++++++++++ lib/iris/tests/unit/pandas/test_pandas.py | 19 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/lib/iris/pandas.py b/lib/iris/pandas.py index 78669eceb3..a345eaa0f7 100644 --- a/lib/iris/pandas.py +++ b/lib/iris/pandas.py @@ -28,6 +28,7 @@ from iris._deprecation import warn_deprecated from iris.coords import AncillaryVariable, AuxCoord, CellMeasure, DimCoord from iris.cube import Cube, CubeList +from iris.util import new_axis from iris.warnings import IrisIgnoringWarning @@ -827,6 +828,9 @@ def merge_metadata(meta_var_list): ) return data_frame + if getattr(cube, "ndim", None) is not None and (is_scalar := cube.ndim == 0): + cube = new_axis(cube) + if iris.FUTURE.pandas_ndim: # Checks if not isinstance(cube, iris.cube.Cube): @@ -893,4 +897,10 @@ def merge_metadata(meta_var_list): result = data_frame + if is_scalar: + if isinstance(result.index, pd.MultiIndex): + result.index.names = [None] * result.index.nlevels + else: + result.index.name = None + return result diff --git a/lib/iris/tests/unit/pandas/test_pandas.py b/lib/iris/tests/unit/pandas/test_pandas.py index 2eae1249a7..6f88b04e3b 100644 --- a/lib/iris/tests/unit/pandas/test_pandas.py +++ b/lib/iris/tests/unit/pandas/test_pandas.py @@ -164,6 +164,16 @@ def test_copy_masked_false(self): class TestAsDataFrame(tests.IrisTest): """Test conversion of 2D cubes to Pandas using as_data_frame().""" + def test_scalar_cube(self): + cube = Cube(1.0) + data_frame = iris.pandas.as_data_frame(cube) + expected_index = [0] + expected_columns = [0] + self.assertArrayEqual(data_frame, cube.data) + self.assertArrayEqual(data_frame.index, expected_index) + self.assertArrayEqual(data_frame.columns, expected_columns) + self.assertIsNone(data_frame.index.name) + def test_no_dim_coords(self): cube = Cube(np.array([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]), long_name="foo") expected_index = [0, 1] @@ -323,6 +333,15 @@ class TestAsDataFrameNDim(tests.IrisTest): def _activate_pandas_ndim(self, activate_pandas_ndim): pass + def test_scalar_cube(self): + cube = Cube(1.0, long_name="foo") + data_frame = iris.pandas.as_data_frame(cube) + expected_index = [0] + self.assertArrayEqual(data_frame.foo.values, cube.data) + self.assertEqual(data_frame.index.nlevels, 1) + self.assertIsNone(data_frame.index.names[0]) + self.assertArrayEqual(data_frame.index.levels[0], expected_index) + def test_no_dim_coords(self): cube = Cube(np.array([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]), long_name="foo") expected_dim0 = np.repeat([0, 1], 5) From 51c2079c051fc7e7f29f0dcbc87cf24a6f5d04c3 Mon Sep 17 00:00:00 2001 From: Bill Little Date: Wed, 16 Jul 2025 21:40:11 +0100 Subject: [PATCH 2/3] add whatsnew entry --- docs/src/whatsnew/latest.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst index dc32b9a1a7..592b99b486 100644 --- a/docs/src/whatsnew/latest.rst +++ b/docs/src/whatsnew/latest.rst @@ -90,12 +90,16 @@ This document explains the changes made to Iris for this release #. `@stephenworsley`_ fixed a bug which caused :meth:`~iris.cube.CubeList.concatenate_cube` to fail when concatenating over multiple axes. (:pull:`6533`) +#. `@bjlittle`_ fixed :func:`~iris.pandas.as_data_frame` to correctly convert a + scalar cube to a :class:`pandas.DataFrame`. (:issue:`6419`, :pull:`6567`) + 💣 Incompatible Changes ======================= #. N/A + 🚀 Performance Enhancements =========================== @@ -130,6 +134,7 @@ This document explains the changes made to Iris for this release #. `@tkknight`_ updated image to ensure it renders correctly using various web browsers on Windows and Linux. (:pull:`6560`) + 💼 Internal =========== From d7ffd17ddb6ae5af16d64f17c0c99e908de2ff74 Mon Sep 17 00:00:00 2001 From: Bill Little Date: Wed, 16 Jul 2025 21:52:48 +0100 Subject: [PATCH 3/3] add comments --- lib/iris/pandas.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/iris/pandas.py b/lib/iris/pandas.py index a345eaa0f7..b23b31dff6 100644 --- a/lib/iris/pandas.py +++ b/lib/iris/pandas.py @@ -829,6 +829,7 @@ def merge_metadata(meta_var_list): return data_frame if getattr(cube, "ndim", None) is not None and (is_scalar := cube.ndim == 0): + # promote the scalar cube to a 1D cube, and convert in the same way as a 1D cube cube = new_axis(cube) if iris.FUTURE.pandas_ndim: @@ -898,6 +899,8 @@ def merge_metadata(meta_var_list): result = data_frame if is_scalar: + # clear the promoted dimension name associated with any + # indices of the dataframe if isinstance(result.index, pd.MultiIndex): result.index.names = [None] * result.index.nlevels else: