Skip to content

Commit c25fbde

Browse files
committed
DEPR: Panel deprecated
closes pandas-dev#13563 on top of pandas-dev#15677 Author: Jeff Reback <[email protected]> Closes pandas-dev#15601 from jreback/panel and squashes the following commits: 04104a7 [Jeff Reback] fine grained catching warnings in tests f8800dc [Jeff Reback] add numpy reference for searchsorted fa136dd [Jeff Reback] doc correction c39453a [Jeff Reback] add perf optimization in searchsorted for FrozenNDArray 0e9c4a4 [Jeff Reback] fix docs as per review & column name changes 3df0abe [Jeff Reback] remove Panel from doc-strings, catch internal warning on Panel construction 755606d [Jeff Reback] more docs d04db2e [Jeff Reback] add deprecate_panel section to docs 538b8e8 [Jeff Reback] pep fix 912d523 [Jeff Reback] TST: separate out test_append_to_multiple_dropna to two tests; when drop=False this is sometimes failing a2625ba [Jeff Reback] remove most Term references in test_pytables.py cd5b6b8 [Jeff Reback] DEPR: Panel deprecated 6b20ddc [Jeff Reback] fix names on return structure f41d3df [Jeff Reback] API: df.rolling(..).corr()/cov() when pairwise=True to return MI DataFrame 84e788b [Jeff Reback] BUG/PERF: handle a slice correctly in get_level_indexer
1 parent c4dca36 commit c25fbde

15 files changed

+3193
-2724
lines changed

doc/source/computation.rst

+15-5
Original file line numberDiff line numberDiff line change
@@ -505,13 +505,18 @@ two ``Series`` or any combination of ``DataFrame/Series`` or
505505
- ``DataFrame/DataFrame``: by default compute the statistic for matching column
506506
names, returning a DataFrame. If the keyword argument ``pairwise=True`` is
507507
passed then computes the statistic for each pair of columns, returning a
508-
``Panel`` whose ``items`` are the dates in question (see :ref:`the next section
508+
``MultiIndexed DataFrame`` whose ``index`` are the dates in question (see :ref:`the next section
509509
<stats.moments.corr_pairwise>`).
510510

511511
For example:
512512

513513
.. ipython:: python
514514
515+
df = pd.DataFrame(np.random.randn(1000, 4),
516+
index=pd.date_range('1/1/2000', periods=1000),
517+
columns=['A', 'B', 'C', 'D'])
518+
df = df.cumsum()
519+
515520
df2 = df[:20]
516521
df2.rolling(window=5).corr(df2['B'])
517522
@@ -520,11 +525,16 @@ For example:
520525
Computing rolling pairwise covariances and correlations
521526
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
522527

528+
.. warning::
529+
530+
Prior to version 0.20.0 if ``pairwise=True`` was passed, a ``Panel`` would be returned.
531+
This will now return a 2-level MultiIndexed DataFrame, see the whatsnew :ref:`here <whatsnew_0200.api_breaking.rolling_pairwise>`
532+
523533
In financial data analysis and other fields it's common to compute covariance
524534
and correlation matrices for a collection of time series. Often one is also
525535
interested in moving-window covariance and correlation matrices. This can be
526536
done by passing the ``pairwise`` keyword argument, which in the case of
527-
``DataFrame`` inputs will yield a ``Panel`` whose ``items`` are the dates in
537+
``DataFrame`` inputs will yield a MultiIndexed ``DataFrame`` whose ``index`` are the dates in
528538
question. In the case of a single DataFrame argument the ``pairwise`` argument
529539
can even be omitted:
530540

@@ -539,12 +549,12 @@ can even be omitted:
539549
.. ipython:: python
540550
541551
covs = df[['B','C','D']].rolling(window=50).cov(df[['A','B','C']], pairwise=True)
542-
covs[df.index[-50]]
552+
covs.loc['2002-09-22':]
543553
544554
.. ipython:: python
545555
546556
correls = df.rolling(window=50).corr()
547-
correls[df.index[-50]]
557+
correls.loc['2002-09-22':]
548558
549559
You can efficiently retrieve the time series of correlations between two
550560
columns using ``.loc`` indexing:
@@ -557,7 +567,7 @@ columns using ``.loc`` indexing:
557567
.. ipython:: python
558568
559569
@savefig rolling_corr_pairwise_ex.png
560-
correls.loc[:, 'A', 'C'].plot()
570+
correls.loc[:, ('A', 'C')].plot()
561571
562572
.. _stats.aggregate:
563573

doc/source/dsintro.rst

+55
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,11 @@ completion mechanism so they can be tab-completed:
763763
Panel
764764
-----
765765

766+
.. warning::
767+
768+
In 0.20.0, ``Panel`` is deprecated and will be removed in
769+
a future version. See the section :ref:`Deprecate Panel <dsintro.deprecate_panel>`.
770+
766771
Panel is a somewhat less-used, but still important container for 3-dimensional
767772
data. The term `panel data <http://en.wikipedia.org/wiki/Panel_data>`__ is
768773
derived from econometrics and is partially responsible for the name pandas:
@@ -783,6 +788,7 @@ From 3D ndarray with optional axis labels
783788
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
784789

785790
.. ipython:: python
791+
:okwarning:
786792
787793
wp = pd.Panel(np.random.randn(2, 5, 4), items=['Item1', 'Item2'],
788794
major_axis=pd.date_range('1/1/2000', periods=5),
@@ -794,6 +800,7 @@ From dict of DataFrame objects
794800
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
795801

796802
.. ipython:: python
803+
:okwarning:
797804
798805
data = {'Item1' : pd.DataFrame(np.random.randn(4, 3)),
799806
'Item2' : pd.DataFrame(np.random.randn(4, 2))}
@@ -816,6 +823,7 @@ dictionary of DataFrames as above, and the following named parameters:
816823
For example, compare to the construction above:
817824

818825
.. ipython:: python
826+
:okwarning:
819827
820828
pd.Panel.from_dict(data, orient='minor')
821829
@@ -824,6 +832,7 @@ DataFrame objects with mixed-type columns, all of the data will get upcasted to
824832
``dtype=object`` unless you pass ``orient='minor'``:
825833

826834
.. ipython:: python
835+
:okwarning:
827836
828837
df = pd.DataFrame({'a': ['foo', 'bar', 'baz'],
829838
'b': np.random.randn(3)})
@@ -851,6 +860,7 @@ This method was introduced in v0.7 to replace ``LongPanel.to_long``, and convert
851860
a DataFrame with a two-level index to a Panel.
852861

853862
.. ipython:: python
863+
:okwarning:
854864
855865
midx = pd.MultiIndex(levels=[['one', 'two'], ['x','y']], labels=[[1,1,0,0],[1,0,1,0]])
856866
df = pd.DataFrame({'A' : [1, 2, 3, 4], 'B': [5, 6, 7, 8]}, index=midx)
@@ -880,6 +890,7 @@ A Panel can be rearranged using its ``transpose`` method (which does not make a
880890
copy by default unless the data are heterogeneous):
881891

882892
.. ipython:: python
893+
:okwarning:
883894
884895
wp.transpose(2, 0, 1)
885896
@@ -909,6 +920,7 @@ Squeezing
909920
Another way to change the dimensionality of an object is to ``squeeze`` a 1-len object, similar to ``wp['Item1']``
910921

911922
.. ipython:: python
923+
:okwarning:
912924
913925
wp.reindex(items=['Item1']).squeeze()
914926
wp.reindex(items=['Item1'], minor=['B']).squeeze()
@@ -923,12 +935,55 @@ for more on this. To convert a Panel to a DataFrame, use the ``to_frame``
923935
method:
924936

925937
.. ipython:: python
938+
:okwarning:
926939
927940
panel = pd.Panel(np.random.randn(3, 5, 4), items=['one', 'two', 'three'],
928941
major_axis=pd.date_range('1/1/2000', periods=5),
929942
minor_axis=['a', 'b', 'c', 'd'])
930943
panel.to_frame()
931944
945+
946+
.. _dsintro.deprecate_panel:
947+
948+
Deprecate Panel
949+
---------------
950+
951+
Over the last few years, pandas has increased in both breadth and depth, with new features,
952+
datatype support, and manipulation routines. As a result, supporting efficient indexing and functional
953+
routines for ``Series``, ``DataFrame`` and ``Panel`` has contributed to an increasingly fragmented and
954+
difficult-to-understand codebase.
955+
956+
The 3-d structure of a ``Panel`` is much less common for many types of data analysis,
957+
than the 1-d of the ``Series`` or the 2-D of the ``DataFrame``. Going forward it makes sense for
958+
pandas to focus on these areas exclusively.
959+
960+
Oftentimes, one can simply use a MultiIndex ``DataFrame`` for easily working with higher dimensional data.
961+
962+
In additon, the ``xarray`` package was built from the ground up, specifically in order to
963+
support the multi-dimensional analysis that is one of ``Panel`` s main usecases.
964+
`Here is a link to the xarray panel-transition documentation <http://xarray.pydata.org/en/stable/pandas.html#panel-transition>`__.
965+
966+
.. ipython:: python
967+
:okwarning:
968+
969+
p = tm.makePanel()
970+
p
971+
972+
Convert to a MultiIndex DataFrame
973+
974+
.. ipython:: python
975+
:okwarning:
976+
977+
p.to_frame()
978+
979+
Alternatively, one can convert to an xarray ``DataArray``.
980+
981+
.. ipython:: python
982+
983+
p.to_xarray()
984+
985+
You can see the full-documentation for the `xarray package <http://xarray.pydata.org/en/stable/>`__.
986+
932987
.. _dsintro.panelnd:
933988
.. _dsintro.panel4d:
934989

doc/source/whatsnew/v0.20.0.txt

+75
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,16 @@ users upgrade to this version.
1010
Highlights include:
1111

1212
- The ``.ix`` indexer has been deprecated, see :ref:`here <whatsnew_0200.api_breaking.deprecate_ix>`
13+
- ``Panel`` has been deprecated, see :ref:`here <whatsnew_0200.api_breaking.deprecate_panel>`
1314
- Improved user API when accessing levels in ``.groupby()``, see :ref:`here <whatsnew_0200.enhancements.groupby_access>`
1415
- Improved support for UInt64 dtypes, see :ref:`here <whatsnew_0200.enhancements.uint64_support>`
1516
- A new orient for JSON serialization, ``orient='table'``, that uses the Table Schema spec, see :ref:`here <whatsnew_0200.enhancements.table_schema>`
17+
- Window Binary Corr/Cov operations return a MultiIndexed ``DataFrame`` rather than a ``Panel``, as ``Panel`` is now deprecated, see :ref:`here <whatsnew_0200.api_breaking.rolling_pairwise>`
1618
- Support for S3 handling now uses ``s3fs``, see :ref:`here <whatsnew_0200.api_breaking.s3>`
1719
- Google BigQuery support now uses the ``pandas-gbq`` library, see :ref:`here <whatsnew_0200.api_breaking.gbq>`
1820
- Switched the test framework to use `pytest <http://doc.pytest.org/en/latest>`__ (:issue:`13097`)
1921

22+
2023
Check the :ref:`API Changes <whatsnew_0200.api_breaking>` and :ref:`deprecations <whatsnew_0200.deprecations>` before updating.
2124

2225
.. contents:: What's new in v0.20.0
@@ -425,6 +428,33 @@ Using ``.iloc``. Here we will get the location of the 'A' column, then use *posi
425428
df.iloc[[0, 2], df.columns.get_loc('A')]
426429

427430

431+
.. _whatsnew_0200.api_breaking.deprecate_panel:
432+
433+
Deprecate Panel
434+
^^^^^^^^^^^^^^^
435+
436+
``Panel`` is deprecated and will be removed in a future version. The recommended way to represent 3-D data are
437+
with a ``MultiIndex``on a ``DataFrame`` via the :meth:`~Panel.to_frame` or with the `xarray package <http://xarray.pydata.org/en/stable/>`__. Pandas
438+
provides a :meth:`~Panel.to_xarray` method to automate this conversion. See the documentation :ref:`Deprecate Panel <dsintro.deprecate_panel>`. (:issue:`13563`).
439+
440+
.. ipython:: python
441+
:okwarning:
442+
443+
p = tm.makePanel()
444+
p
445+
446+
Convert to a MultiIndex DataFrame
447+
448+
.. ipython:: python
449+
450+
p.to_frame()
451+
452+
Convert to an xarray DataArray
453+
454+
.. ipython:: python
455+
456+
p.to_xarray()
457+
428458
.. _whatsnew.api_breaking.io_compat:
429459

430460
Possible incompat for HDF5 formats for pandas < 0.13.0
@@ -836,6 +866,51 @@ New Behavior:
836866

837867
df.groupby('A').agg([np.mean, np.std, np.min, np.max])
838868

869+
.. _whatsnew_0200.api_breaking.rolling_pairwise:
870+
871+
Window Binary Corr/Cov operations return a MultiIndex DataFrame
872+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
873+
874+
A binary window operation, like ``.corr()`` or ``.cov()``, when operating on a ``.rolling(..)``, ``.expanding(..)``, or ``.ewm(..)`` object,
875+
will now return a 2-level ``MultiIndexed DataFrame`` rather than a ``Panel``, as ``Panel`` is now deprecated,
876+
see :ref:`here <_whatsnew_0200.api_breaking.deprecate_panel>`. These are equivalent in function,
877+
but MultiIndexed ``DataFrame`` s enjoy more support in pandas.
878+
See the section on :ref:`Windowed Binary Operations <stats.moments.binary>` for more information. (:issue:`15677`)
879+
880+
.. ipython:: python
881+
882+
np.random.seed(1234)
883+
df = pd.DataFrame(np.random.rand(100, 2),
884+
columns=pd.Index(['A', 'B'], name='bar'),
885+
index=pd.date_range('20160101',
886+
periods=100, freq='D', name='foo'))
887+
df.tail()
888+
889+
Old Behavior:
890+
891+
.. code-block:: ipython
892+
893+
In [2]: df.rolling(12).corr()
894+
Out[2]:
895+
<class 'pandas.core.panel.Panel'>
896+
Dimensions: 100 (items) x 2 (major_axis) x 2 (minor_axis)
897+
Items axis: 2016-01-01 00:00:00 to 2016-04-09 00:00:00
898+
Major_axis axis: A to B
899+
Minor_axis axis: A to B
900+
901+
New Behavior:
902+
903+
.. ipython:: python
904+
905+
res = df.rolling(12).corr()
906+
res.tail()
907+
908+
Retrieving a correlation matrix for a cross-section
909+
910+
.. ipython:: python
911+
912+
df.rolling(12).corr().loc['2016-04-07']
913+
839914
.. _whatsnew_0200.api_breaking.hdfstore_where:
840915

841916
HDFStore where string comparison

pandas/core/panel.py

+13-3
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@
44
# pylint: disable=E1103,W0231,W0212,W0621
55
from __future__ import division
66

7-
import warnings
8-
97
import numpy as np
10-
8+
import warnings
119
from pandas.types.cast import (infer_dtype_from_scalar,
1210
maybe_cast_item)
1311
from pandas.types.common import (is_integer, is_list_like,
@@ -132,6 +130,18 @@ def _constructor(self):
132130

133131
def __init__(self, data=None, items=None, major_axis=None, minor_axis=None,
134132
copy=False, dtype=None):
133+
# deprecation GH13563
134+
warnings.warn("\nPanel is deprecated and will be removed in a "
135+
"future version.\nThe recommended way to represent "
136+
"these types of 3-dimensional data are with a "
137+
"MultiIndex on a DataFrame, via the "
138+
"Panel.to_frame() method\n"
139+
"Alternatively, you can use the xarray package "
140+
"http://xarray.pydata.org/en/stable/.\n"
141+
"Pandas provides a `.to_xarray()` method to help "
142+
"automate this conversion.\n",
143+
DeprecationWarning, stacklevel=3)
144+
135145
self._init_data(data=data, items=items, major_axis=major_axis,
136146
minor_axis=minor_axis, copy=copy, dtype=dtype)
137147

0 commit comments

Comments
 (0)