Skip to content

Commit 2000684

Browse files
authored
support scalar cube to pandas dataframe (#6567)
* support scalar cube to pandas dataframe * add whatsnew entry * add comments
1 parent 13e3d9f commit 2000684

File tree

3 files changed

+37
-0
lines changed

3 files changed

+37
-0
lines changed

docs/src/whatsnew/latest.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,16 @@ This document explains the changes made to Iris for this release
9090
#. `@stephenworsley`_ fixed a bug which caused :meth:`~iris.cube.CubeList.concatenate_cube`
9191
to fail when concatenating over multiple axes. (:pull:`6533`)
9292

93+
#. `@bjlittle`_ fixed :func:`~iris.pandas.as_data_frame` to correctly convert a
94+
scalar cube to a :class:`pandas.DataFrame`. (:issue:`6419`, :pull:`6567`)
95+
9396

9497
💣 Incompatible Changes
9598
=======================
9699

97100
#. N/A
98101

102+
99103
🚀 Performance Enhancements
100104
===========================
101105

@@ -130,6 +134,7 @@ This document explains the changes made to Iris for this release
130134
#. `@tkknight`_ updated image to ensure it renders correctly using various web browsers
131135
on Windows and Linux. (:pull:`6560`)
132136

137+
133138
💼 Internal
134139
===========
135140

lib/iris/pandas.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from iris._deprecation import warn_deprecated
2929
from iris.coords import AncillaryVariable, AuxCoord, CellMeasure, DimCoord
3030
from iris.cube import Cube, CubeList
31+
from iris.util import new_axis
3132
from iris.warnings import IrisIgnoringWarning
3233

3334

@@ -827,6 +828,10 @@ def merge_metadata(meta_var_list):
827828
)
828829
return data_frame
829830

831+
if getattr(cube, "ndim", None) is not None and (is_scalar := cube.ndim == 0):
832+
# promote the scalar cube to a 1D cube, and convert in the same way as a 1D cube
833+
cube = new_axis(cube)
834+
830835
if iris.FUTURE.pandas_ndim:
831836
# Checks
832837
if not isinstance(cube, iris.cube.Cube):
@@ -893,4 +898,12 @@ def merge_metadata(meta_var_list):
893898

894899
result = data_frame
895900

901+
if is_scalar:
902+
# clear the promoted dimension name associated with any
903+
# indices of the dataframe
904+
if isinstance(result.index, pd.MultiIndex):
905+
result.index.names = [None] * result.index.nlevels
906+
else:
907+
result.index.name = None
908+
896909
return result

lib/iris/tests/unit/pandas/test_pandas.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,16 @@ def test_copy_masked_false(self):
164164
class TestAsDataFrame(tests.IrisTest):
165165
"""Test conversion of 2D cubes to Pandas using as_data_frame()."""
166166

167+
def test_scalar_cube(self):
168+
cube = Cube(1.0)
169+
data_frame = iris.pandas.as_data_frame(cube)
170+
expected_index = [0]
171+
expected_columns = [0]
172+
self.assertArrayEqual(data_frame, cube.data)
173+
self.assertArrayEqual(data_frame.index, expected_index)
174+
self.assertArrayEqual(data_frame.columns, expected_columns)
175+
self.assertIsNone(data_frame.index.name)
176+
167177
def test_no_dim_coords(self):
168178
cube = Cube(np.array([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]), long_name="foo")
169179
expected_index = [0, 1]
@@ -323,6 +333,15 @@ class TestAsDataFrameNDim(tests.IrisTest):
323333
def _activate_pandas_ndim(self, activate_pandas_ndim):
324334
pass
325335

336+
def test_scalar_cube(self):
337+
cube = Cube(1.0, long_name="foo")
338+
data_frame = iris.pandas.as_data_frame(cube)
339+
expected_index = [0]
340+
self.assertArrayEqual(data_frame.foo.values, cube.data)
341+
self.assertEqual(data_frame.index.nlevels, 1)
342+
self.assertIsNone(data_frame.index.names[0])
343+
self.assertArrayEqual(data_frame.index.levels[0], expected_index)
344+
326345
def test_no_dim_coords(self):
327346
cube = Cube(np.array([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]), long_name="foo")
328347
expected_dim0 = np.repeat([0, 1], 5)

0 commit comments

Comments
 (0)