diff --git a/doc/pandas.rst b/doc/pandas.rst index 1538fced648..70152d01908 100644 --- a/doc/pandas.rst +++ b/doc/pandas.rst @@ -151,10 +151,11 @@ However, you will need to set dimension names explicitly, either with the Transitioning from pandas.Panel to xarray ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -:py:class:`~pandas.Panel`, pandas' data structure for 3D arrays, has always +``Panel``, pandas' data structure for 3D arrays, has always been a second class data structure compared to the Series and DataFrame. To allow pandas developers to focus more on its core functionality built around -the DataFrame, pandas plans to eventually deprecate Panel. +the DataFrame, panads has deprecated ``Panel``. It will be removed in pandas +0.25. xarray has most of ``Panel``'s features, a more explicit API (particularly around indexing), and the ability to scale to >3 dimensions with the same interface. @@ -172,28 +173,41 @@ So you can represent a Panel, in two ways: Let's take a look: .. ipython:: python - :okwarning: - panel = pd.Panel(np.random.rand(2, 3, 4), items=list('ab'), major_axis=list('mno'), - minor_axis=pd.date_range(start='2000', periods=4, name='date')) - panel + data = np.random.RandomState(0).rand(2, 3, 4) + items = list('ab') + major_axis = list('mno') + minor_axis = pd.date_range(start='2000', periods=4, name='date') -As a DataArray: +With old versions of pandas (prior to 0.25), this could stored in a ``Panel``: + +.. ipython:: + :verbatim: + + In [1]: pd.Panel(data, items, major_axis, minor_axis) + Out[1]: + + Dimensions: 2 (items) x 3 (major_axis) x 4 (minor_axis) + Items axis: a to b + Major_axis axis: m to o + Minor_axis axis: 2000-01-01 00:00:00 to 2000-01-04 00:00:00 + +To put this data in a ``DataArray``, write: .. ipython:: python - # or equivalently, with Panel.to_xarray() - xr.DataArray(panel) + array = xr.DataArray(data, [items, major_axis, minor_axis]) + array As you can see, there are three dimensions (each is also a coordinate). Two of -the axes of the panel were unnamed, so have been assigned ``dim_0`` and -``dim_1`` respectively, while the third retains its name ``date``. +the axes of were unnamed, so have been assigned ``dim_0`` and ``dim_1`` +respectively, while the third retains its name ``date``. -As a Dataset: +You can also easily convert this data into ``Dataset``: .. ipython:: python - xr.Dataset(panel) + array.to_dataset(dim='dim_0') Here, there are two data variables, each representing a DataFrame on panel's ``items`` axis, and labelled as such. Each variable is a 2D array of the diff --git a/doc/whats-new.rst b/doc/whats-new.rst index ccc323c0c02..71ea5865dd7 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -126,6 +126,9 @@ Bug fixes - Add explicit pytest markers, now required by pytest (:issue:`3032`). By `Maximilian Roos `_. +- Fix to ensure that xarray can still be imported with pandas 0.25, which will + remove `pd.Panel`. + By `Stephan Hoyer `_. .. _whats-new.0.12.1: diff --git a/xarray/core/dataarray.py b/xarray/core/dataarray.py index 5472f5e7b4d..d41f914bed1 100644 --- a/xarray/core/dataarray.py +++ b/xarray/core/dataarray.py @@ -264,7 +264,7 @@ def __init__( coords = [data.index, data.columns] elif isinstance(data, (pd.Index, IndexVariable)): coords = [data] - elif isinstance(data, pd.Panel): + elif hasattr(pd, 'Panel') and isinstance(data, pd.Panel): coords = [data.items, data.major_axis, data.minor_axis] if dims is None: dims = getattr(data, 'dims', getattr(coords, 'dims', None)) @@ -1825,8 +1825,7 @@ def reduce(self, func: Callable[..., Any], **kwargs) return self._replace_maybe_drop_dims(var) - def to_pandas(self) -> Union[ - 'DataArray', pd.Series, pd.DataFrame, pd.Panel]: + def to_pandas(self) -> Union['DataArray', pd.Series, pd.DataFrame]: """Convert this array into a pandas object with the same shape. The type of the returned object depends on the number of DataArray @@ -1845,8 +1844,9 @@ def to_pandas(self) -> Union[ # attributes that correspond to their indexes into a separate module? constructors = {0: lambda x: x, 1: pd.Series, - 2: pd.DataFrame, - 3: pd.Panel} + 2: pd.DataFrame} + if hasattr(pd, 'Panel'): + constructors[3] = pd.Panel try: constructor = constructors[self.ndim] except KeyError: diff --git a/xarray/core/merge.py b/xarray/core/merge.py index 90bd0166425..08391c994bc 100644 --- a/xarray/core/merge.py +++ b/xarray/core/merge.py @@ -15,7 +15,9 @@ from .dataset import Dataset -PANDAS_TYPES = (pd.Series, pd.DataFrame, pd.Panel) +PANDAS_TYPES = ( + (pd.Series, pd.DataFrame) + (pd.Panel,) if hasattr(pd, 'Panel') else () +) _VALID_COMPAT = Frozen({'identical': 0, 'equals': 1,