Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DEPR: remove PanelGroupBy, disable DataFrame.to_panel #25047

Merged
merged 5 commits into from
Feb 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v0.25.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Deprecations

Removal of prior version deprecations/changes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- Removed (parts of) :class:`Panel` (:issue:`25047`)
-
-
-
Expand Down
40 changes: 1 addition & 39 deletions pandas/core/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -1974,45 +1974,7 @@ def to_panel(self):
-------
panel : Panel
"""
# only support this kind for now
if (not isinstance(self.index, MultiIndex) or # pragma: no cover
len(self.index.levels) != 2):
raise NotImplementedError('Only 2-level MultiIndex are supported.')

if not self.index.is_unique:
raise ValueError("Can't convert non-uniquely indexed "
"DataFrame to Panel")

self._consolidate_inplace()

# minor axis must be sorted
if self.index.lexsort_depth < 2:
selfsorted = self.sort_index(level=0)
else:
selfsorted = self

major_axis, minor_axis = selfsorted.index.levels
major_codes, minor_codes = selfsorted.index.codes
shape = len(major_axis), len(minor_axis)

# preserve names, if any
major_axis = major_axis.copy()
major_axis.name = self.index.names[0]

minor_axis = minor_axis.copy()
minor_axis.name = self.index.names[1]

# create new axes
new_axes = [selfsorted.columns, major_axis, minor_axis]

# create new manager
new_mgr = selfsorted._data.reshape_nd(axes=new_axes,
labels=[major_codes,
minor_codes],
shape=shape,
ref_items=selfsorted.columns)

return self._constructor_expanddim(new_mgr)
raise NotImplementedError("Panel is being removed in pandas 0.25.0.")

@deprecate_kwarg(old_arg_name='encoding', new_arg_name=None)
def to_stata(self, fname, convert_dates=None, write_index=True,
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/groupby/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from pandas.core.groupby.groupby import GroupBy # noqa: F401
from pandas.core.groupby.generic import ( # noqa: F401
SeriesGroupBy, DataFrameGroupBy, PanelGroupBy)
SeriesGroupBy, DataFrameGroupBy)
from pandas.core.groupby.grouper import Grouper # noqa: F401
90 changes: 1 addition & 89 deletions pandas/core/groupby/generic.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Define the SeriesGroupBy, DataFrameGroupBy, and PanelGroupBy
Define the SeriesGroupBy and DataFrameGroupBy
classes that hold the groupby interfaces (and some implementations).

These are user facing as the result of the ``df.groupby(...)`` operations,
Expand Down Expand Up @@ -39,7 +39,6 @@
from pandas.core.index import CategoricalIndex, Index, MultiIndex
import pandas.core.indexes.base as ibase
from pandas.core.internals import BlockManager, make_block
from pandas.core.panel import Panel
from pandas.core.series import Series

from pandas.plotting._core import boxplot_frame_groupby
Expand Down Expand Up @@ -1586,90 +1585,3 @@ def groupby_series(obj, col=None):
return results

boxplot = boxplot_frame_groupby


class PanelGroupBy(NDFrameGroupBy):

def aggregate(self, arg, *args, **kwargs):
return super(PanelGroupBy, self).aggregate(arg, *args, **kwargs)

agg = aggregate

def _iterate_slices(self):
if self.axis == 0:
# kludge
if self._selection is None:
slice_axis = self._selected_obj.items
else:
slice_axis = self._selection_list
slicer = lambda x: self._selected_obj[x]
else:
raise NotImplementedError("axis other than 0 is not supported")

for val in slice_axis:
if val in self.exclusions:
continue

yield val, slicer(val)

def aggregate(self, arg, *args, **kwargs):
"""
Aggregate using input function or dict of {column -> function}

Parameters
----------
arg : function or dict
Function to use for aggregating groups. If a function, must either
work when passed a Panel or when passed to Panel.apply. If
pass a dict, the keys must be DataFrame column names

Returns
-------
aggregated : Panel
"""
if isinstance(arg, compat.string_types):
return getattr(self, arg)(*args, **kwargs)

return self._aggregate_generic(arg, *args, **kwargs)

def _wrap_generic_output(self, result, obj):
if self.axis == 0:
new_axes = list(obj.axes)
new_axes[0] = self.grouper.result_index
elif self.axis == 1:
x, y, z = obj.axes
new_axes = [self.grouper.result_index, z, x]
else:
x, y, z = obj.axes
new_axes = [self.grouper.result_index, y, x]

result = Panel._from_axes(result, new_axes)

if self.axis == 1:
result = result.swapaxes(0, 1).swapaxes(0, 2)
elif self.axis == 2:
result = result.swapaxes(0, 2)

return result

def _aggregate_item_by_item(self, func, *args, **kwargs):
obj = self._obj_with_exclusions
result = {}

if self.axis > 0:
for item in obj:
try:
itemg = DataFrameGroupBy(obj[item],
axis=self.axis - 1,
grouper=self.grouper)
result[item] = itemg.aggregate(func, *args, **kwargs)
except (ValueError, TypeError):
raise
new_axes = list(obj.axes)
new_axes[self.axis] = self.grouper.result_index
return Panel._from_axes(result, new_axes)
else:
raise ValueError("axis value must be greater than 0")

def _wrap_aggregated_output(self, output, names=None):
raise AbstractMethodError(self)
4 changes: 1 addition & 3 deletions pandas/core/panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -917,9 +917,7 @@ def groupby(self, function, axis='major'):
-------
grouped : PanelGroupBy
"""
from pandas.core.groupby import PanelGroupBy
axis = self._get_axis_number(axis)
return PanelGroupBy(self, function, axis=axis)
raise NotImplementedError("Panel is removed in pandas 0.25.0")

def to_frame(self, filter_observations=True):
"""
Expand Down
9 changes: 2 additions & 7 deletions pandas/core/resample.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import pandas.core.algorithms as algos
from pandas.core.generic import _shared_docs
from pandas.core.groupby.base import GroupByMixin
from pandas.core.groupby.generic import PanelGroupBy, SeriesGroupBy
from pandas.core.groupby.generic import SeriesGroupBy
from pandas.core.groupby.groupby import (
GroupBy, _GroupBy, _pipe_template, groupby)
from pandas.core.groupby.grouper import Grouper
Expand Down Expand Up @@ -340,12 +340,7 @@ def _groupby_and_aggregate(self, how, grouper=None, *args, **kwargs):

obj = self._selected_obj

try:
grouped = groupby(obj, by=None, grouper=grouper, axis=self.axis)
except TypeError:

# panel grouper
grouped = PanelGroupBy(obj, grouper=grouper, axis=self.axis)
grouped = groupby(obj, by=None, grouper=grouper, axis=self.axis)

try:
if isinstance(obj, ABCDataFrame) and compat.callable(how):
Expand Down
39 changes: 2 additions & 37 deletions pandas/io/pytables.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
PeriodIndex, Series, SparseDataFrame, SparseSeries, TimedeltaIndex, compat,
concat, isna, to_datetime)
from pandas.core import config
from pandas.core.algorithms import match, unique
from pandas.core.algorithms import unique
from pandas.core.arrays.categorical import (
Categorical, _factorize_from_iterables)
from pandas.core.arrays.sparse import BlockIndex, IntIndex
Expand Down Expand Up @@ -3944,29 +3944,7 @@ def read(self, where=None, columns=None, **kwargs):
objs.append(obj)

else:
warnings.warn(duplicate_doc, DuplicateWarning, stacklevel=5)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jreback this is the part of this PR (and the larger process) that I'm least confident about. Are we sure we want to rip this out entirely or should it somehow be adapted to not use Panel?


# reconstruct
long_index = MultiIndex.from_arrays(
[i.values for i in self.index_axes])

for c in self.values_axes:
lp = DataFrame(c.data, index=long_index, columns=c.values)

# need a better algorithm
tuple_index = long_index.values

unique_tuples = unique(tuple_index)
unique_tuples = com.asarray_tuplesafe(unique_tuples)

indexer = match(unique_tuples, tuple_index)
indexer = ensure_platform_int(indexer)

new_index = long_index.take(indexer)
new_values = lp.values.take(indexer, axis=0)

lp = DataFrame(new_values, index=new_index, columns=lp.columns)
objs.append(lp.to_panel())
raise NotImplementedError("Panel is removed in pandas 0.25.0")

# create the composite object
if len(objs) == 1:
Expand Down Expand Up @@ -4875,16 +4853,3 @@ def select_coords(self):
return self.coordinates

return np.arange(start, stop)

# utilities ###


def timeit(key, df, fn=None, remove=True, **kwargs):
jreback marked this conversation as resolved.
Show resolved Hide resolved
if fn is None:
fn = 'timeit.h5'
store = HDFStore(fn, mode='w')
store.append(key, df, **kwargs)
store.close()

if remove:
os.remove(fn)
5 changes: 1 addition & 4 deletions pandas/tests/dtypes/test_generic.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-

from warnings import catch_warnings, simplefilter
from warnings import catch_warnings

import numpy as np

Expand Down Expand Up @@ -39,9 +39,6 @@ def test_abc_types(self):
assert isinstance(pd.Int64Index([1, 2, 3]), gt.ABCIndexClass)
assert isinstance(pd.Series([1, 2, 3]), gt.ABCSeries)
assert isinstance(self.df, gt.ABCDataFrame)
with catch_warnings(record=True):
simplefilter('ignore', FutureWarning)
assert isinstance(self.df.to_panel(), gt.ABCPanel)
assert isinstance(self.sparse_series, gt.ABCSparseSeries)
assert isinstance(self.sparse_array, gt.ABCSparseArray)
assert isinstance(self.sparse_frame, gt.ABCSparseDataFrame)
Expand Down
25 changes: 1 addition & 24 deletions pandas/tests/frame/test_subclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import pytest

import pandas as pd
from pandas import DataFrame, Index, MultiIndex, Panel, Series
from pandas import DataFrame, Index, MultiIndex, Series
from pandas.tests.frame.common import TestData
import pandas.util.testing as tm

Expand Down Expand Up @@ -125,29 +125,6 @@ def test_indexing_sliced(self):
tm.assert_series_equal(res, exp)
assert isinstance(res, tm.SubclassedSeries)

@pytest.mark.filterwarnings("ignore:\\nPanel:FutureWarning")
def test_to_panel_expanddim(self):
# GH 9762

class SubclassedFrame(DataFrame):

@property
def _constructor_expanddim(self):
return SubclassedPanel

class SubclassedPanel(Panel):
pass

index = MultiIndex.from_tuples([(0, 0), (0, 1), (0, 2)])
df = SubclassedFrame({'X': [1, 2, 3], 'Y': [4, 5, 6]}, index=index)
result = df.to_panel()
assert isinstance(result, SubclassedPanel)
expected = SubclassedPanel([[[1, 2, 3]], [[4, 5, 6]]],
items=['X', 'Y'], major_axis=[0],
minor_axis=[0, 1, 2],
dtype='int64')
tm.assert_panel_equal(result, expected)

def test_subclass_attr_err_propagation(self):
# GH 11808
class A(DataFrame):
Expand Down
25 changes: 0 additions & 25 deletions pandas/tests/groupby/test_groupby.py
Original file line number Diff line number Diff line change
Expand Up @@ -1239,31 +1239,6 @@ def _check_work(gp):
# _check_work(panel.groupby(lambda x: x.month, axis=1))


@pytest.mark.filterwarnings("ignore:\\nPanel:FutureWarning")
def test_panel_groupby():
panel = tm.makePanel()
tm.add_nans(panel)
grouped = panel.groupby({'ItemA': 0, 'ItemB': 0, 'ItemC': 1},
axis='items')
agged = grouped.mean()
agged2 = grouped.agg(lambda x: x.mean('items'))

tm.assert_panel_equal(agged, agged2)

tm.assert_index_equal(agged.items, Index([0, 1]))

grouped = panel.groupby(lambda x: x.month, axis='major')
agged = grouped.mean()

exp = Index(sorted(list(set(panel.major_axis.month))))
tm.assert_index_equal(agged.major_axis, exp)

grouped = panel.groupby({'A': 0, 'B': 0, 'C': 1, 'D': 1},
axis='minor')
agged = grouped.mean()
tm.assert_index_equal(agged.minor_axis, Index([0, 1]))


def test_groupby_2d_malformed():
d = DataFrame(index=lrange(2))
d['group'] = ['g1', 'g2']
Expand Down
26 changes: 1 addition & 25 deletions pandas/tests/groupby/test_grouping.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
from pandas.core.groupby.grouper import Grouping
import pandas.util.testing as tm
from pandas.util.testing import (
assert_almost_equal, assert_frame_equal, assert_panel_equal,
assert_series_equal)
assert_almost_equal, assert_frame_equal, assert_series_equal)

# selection
# --------------------------------
Expand Down Expand Up @@ -563,17 +562,7 @@ def test_list_grouper_with_nat(self):
# --------------------------------

class TestGetGroup():

@pytest.mark.filterwarnings("ignore:\\nPanel:FutureWarning")
def test_get_group(self):
wp = tm.makePanel()
grouped = wp.groupby(lambda x: x.month, axis='major')

gp = grouped.get_group(1)
expected = wp.reindex(
major=[x for x in wp.major_axis if x.month == 1])
assert_panel_equal(gp, expected)

# GH 5267
# be datelike friendly
df = DataFrame({'DATE': pd.to_datetime(
Expand Down Expand Up @@ -755,19 +744,6 @@ def test_multi_iter_frame(self, three_group):
for key, group in grouped:
pass

@pytest.mark.filterwarnings("ignore:\\nPanel:FutureWarning")
def test_multi_iter_panel(self):
wp = tm.makePanel()
grouped = wp.groupby([lambda x: x.month, lambda x: x.weekday()],
axis=1)

for (month, wd), group in grouped:
exp_axis = [x
for x in wp.major_axis
if x.month == month and x.weekday() == wd]
expected = wp.reindex(major=exp_axis)
assert_panel_equal(group, expected)

def test_dictify(self, df):
dict(iter(df.groupby('A')))
dict(iter(df.groupby(['A', 'B'])))
Expand Down
Loading