content: # -*- coding: utf-8 -*-
  # pylint: disable=W0612,E1101
  
  from warnings import catch_warnings, simplefilter
  from datetime import datetime
  import operator
  import pytest
  
  import numpy as np
  
  from pandas.core.dtypes.common import is_float_dtype
  from pandas import (Series, DataFrame, Index, date_range, isna, notna,
                      MultiIndex)
  from pandas.core.nanops import nanall, nanany
  from pandas.core.panel import Panel
  
  from pandas.io.formats.printing import pprint_thing
  from pandas import compat
  from pandas.compat import range, lrange, StringIO, OrderedDict, signature
  
  from pandas.tseries.offsets import BDay, MonthEnd
  from pandas.util.testing import (assert_panel_equal, assert_frame_equal,
                                   assert_series_equal, assert_almost_equal,
                                   ensure_clean, makeMixedDataFrame,
                                   makeCustomDataframe as mkdf)
  import pandas.core.panel as panelm
  import pandas.util.testing as tm
  import pandas.util._test_decorators as td
  
  
  def make_test_panel():
      with catch_warnings(record=True):
          simplefilter("ignore", FutureWarning)
          _panel = tm.makePanel()
          tm.add_nans(_panel)
          _panel = _panel.copy()
      return _panel
  
  
  @pytest.mark.filterwarnings("ignore:\\nPanel:FutureWarning")
  class PanelTests(object):
      panel = None
  
      def test_pickle(self):
          unpickled = tm.round_trip_pickle(self.panel)
          assert_frame_equal(unpickled['ItemA'], self.panel['ItemA'])
  
      def test_rank(self):
          pytest.raises(NotImplementedError, lambda: self.panel.rank())
  
      def test_cumsum(self):
          cumsum = self.panel.cumsum()
          assert_frame_equal(cumsum['ItemA'], self.panel['ItemA'].cumsum())
  
      def not_hashable(self):
          c_empty = Panel()
          c = Panel(Panel([[[1]]]))
          pytest.raises(TypeError, hash, c_empty)
          pytest.raises(TypeError, hash, c)
  
  
  @pytest.mark.filterwarnings("ignore:\\nPanel:FutureWarning")
  class SafeForLongAndSparse(object):
  
      def test_repr(self):
          repr(self.panel)
  
      def test_copy_names(self):
          for attr in ('major_axis', 'minor_axis'):
              getattr(self.panel, attr).name = None
              cp = self.panel.copy()
              getattr(cp, attr).name = 'foo'
              assert getattr(self.panel, attr).name is None
  
      def test_iter(self):
          tm.equalContents(list(self.panel), self.panel.items)
  
      def test_count(self):
          f = lambda s: notna(s).sum()
          self._check_stat_op('count', f, obj=self.panel, has_skipna=False)
  
      def test_sum(self):
          self._check_stat_op('sum', np.sum, skipna_alternative=np.nansum)
  
      def test_mean(self):
          self._check_stat_op('mean', np.mean)
  
      @td.skip_if_no("numpy", min_version="1.10.0")
      def test_prod(self):
          self._check_stat_op('prod', np.prod, skipna_alternative=np.nanprod)
  
      @pytest.mark.filterwarnings("ignore:Invalid value:RuntimeWarning")
      @pytest.mark.filterwarnings("ignore:All-NaN:RuntimeWarning")
      def test_median(self):
          def wrapper(x):
              if isna(x).any():
                  return np.nan
              return np.median(x)
  
          self._check_stat_op('median', wrapper)
  
      @pytest.mark.filterwarnings("ignore:Invalid value:RuntimeWarning")
      def test_min(self):
          self._check_stat_op('min', np.min)
  
      @pytest.mark.filterwarnings("ignore:Invalid value:RuntimeWarning")
      def test_max(self):
          self._check_stat_op('max', np.max)
  
      @td.skip_if_no_scipy
      def test_skew(self):
          from scipy.stats import skew
  
          def this_skew(x):
              if len(x) < 3:
                  return np.nan
              return skew(x, bias=False)
  
          self._check_stat_op('skew', this_skew)
  
      def test_var(self):
          def alt(x):
              if len(x) < 2:
                  return np.nan
              return np.var(x, ddof=1)
  
          self._check_stat_op('var', alt)
  
      def test_std(self):
          def alt(x):
              if len(x) < 2:
                  return np.nan
              return np.std(x, ddof=1)
  
          self._check_stat_op('std', alt)
  
      def test_sem(self):
          def alt(x):
              if len(x) < 2:
                  return np.nan
              return np.std(x, ddof=1) / np.sqrt(len(x))
  
          self._check_stat_op('sem', alt)
  
      def _check_stat_op(self, name, alternative, obj=None, has_skipna=True,
                         skipna_alternative=None):
          if obj is None:
              obj = self.panel
  
              # # set some NAs
              # obj.loc[5:10] = np.nan
              # obj.loc[15:20, -2:] = np.nan
  
          f = getattr(obj, name)
  
          if has_skipna:
  
              skipna_wrapper = tm._make_skipna_wrapper(alternative,
                                                       skipna_alternative)
  
              def wrapper(x):
                  return alternative(np.asarray(x))
  
              for i in range(obj.ndim):
                  result = f(axis=i, skipna=False)
                  assert_frame_equal(result, obj.apply(wrapper, axis=i))
          else:
              skipna_wrapper = alternative
              wrapper = alternative
  
          for i in range(obj.ndim):
              result = f(axis=i)
              if name in ['sum', 'prod']:
                  assert_frame_equal(result, obj.apply(skipna_wrapper, axis=i))
  
          pytest.raises(Exception, f, axis=obj.ndim)
  
          # Unimplemented numeric_only parameter.
          if 'numeric_only' in signature(f).args:
              tm.assert_raises_regex(NotImplementedError, name, f,
                                     numeric_only=True)
  
  
  @pytest.mark.filterwarnings("ignore:\\nPanel:FutureWarning")
  class SafeForSparse(object):
  
      def test_get_axis(self):
          assert (self.panel._get_axis(0) is self.panel.items)
          assert (self.panel._get_axis(1) is self.panel.major_axis)
          assert (self.panel._get_axis(2) is self.panel.minor_axis)
  
      def test_set_axis(self):
          new_items = Index(np.arange(len(self.panel.items)))
          new_major = Index(np.arange(len(self.panel.major_axis)))
          new_minor = Index(np.arange(len(self.panel.minor_axis)))
  
          # ensure propagate to potentially prior-cached items too
          item = self.panel['ItemA']
          self.panel.items = new_items
  
          if hasattr(self.panel, '_item_cache'):
              assert 'ItemA' not in self.panel._item_cache
          assert self.panel.items is new_items
  
          # TODO: unused?
          item = self.panel[0]  # noqa
  
          self.panel.major_axis = new_major
          assert self.panel[0].index is new_major
          assert self.panel.major_axis is new_major
  
          # TODO: unused?
          item = self.panel[0]  # noqa
  
          self.panel.minor_axis = new_minor
          assert self.panel[0].columns is new_minor
          assert self.panel.minor_axis is new_minor
  
      def test_get_axis_number(self):
          assert self.panel._get_axis_number('items') == 0
          assert self.panel._get_axis_number('major') == 1
          assert self.panel._get_axis_number('minor') == 2
  
          with tm.assert_raises_regex(ValueError, "No axis named foo"):
              self.panel._get_axis_number('foo')
  
          with tm.assert_raises_regex(ValueError, "No axis named foo"):
              self.panel.__ge__(self.panel, axis='foo')
  
      def test_get_axis_name(self):
          assert self.panel._get_axis_name(0) == 'items'
          assert self.panel._get_axis_name(1) == 'major_axis'
          assert self.panel._get_axis_name(2) == 'minor_axis'
  
      def test_get_plane_axes(self):
          # what to do here?
  
          index, columns = self.panel._get_plane_axes('items')
          index, columns = self.panel._get_plane_axes('major_axis')
          index, columns = self.panel._get_plane_axes('minor_axis')
          index, columns = self.panel._get_plane_axes(0)
  
      def test_truncate(self):
          dates = self.panel.major_axis
          start, end = dates[1], dates[5]
  
          trunced = self.panel.truncate(start, end, axis='major')
          expected = self.panel['ItemA'].truncate(start, end)
  
          assert_frame_equal(trunced['ItemA'], expected)
  
          trunced = self.panel.truncate(before=start, axis='major')
          expected = self.panel['ItemA'].truncate(before=start)
  
          assert_frame_equal(trunced['ItemA'], expected)
  
          trunced = self.panel.truncate(after=end, axis='major')
          expected = self.panel['ItemA'].truncate(after=end)
  
          assert_frame_equal(trunced['ItemA'], expected)
  
      def test_arith(self):
          self._test_op(self.panel, operator.add)
          self._test_op(self.panel, operator.sub)
          self._test_op(self.panel, operator.mul)
          self._test_op(self.panel, operator.truediv)
          self._test_op(self.panel, operator.floordiv)
          self._test_op(self.panel, operator.pow)
  
          self._test_op(self.panel, lambda x, y: y + x)
          self._test_op(self.panel, lambda x, y: y - x)
          self._test_op(self.panel, lambda x, y: y * x)
          self._test_op(self.panel, lambda x, y: y / x)
          self._test_op(self.panel, lambda x, y: y ** x)
  
          self._test_op(self.panel, lambda x, y: x + y)  # panel + 1
          self._test_op(self.panel, lambda x, y: x - y)  # panel - 1
          self._test_op(self.panel, lambda x, y: x * y)  # panel * 1
          self._test_op(self.panel, lambda x, y: x / y)  # panel / 1
          self._test_op(self.panel, lambda x, y: x ** y)  # panel ** 1
  
          pytest.raises(Exception, self.panel.__add__,
                        self.panel['ItemA'])
  
      @staticmethod
      def _test_op(panel, op):
          result = op(panel, 1)
          assert_frame_equal(result['ItemA'], op(panel['ItemA'], 1))
  
      def test_keys(self):
          tm.equalContents(list(self.panel.keys()), self.panel.items)
  
      def test_iteritems(self):
          # Test panel.iteritems(), aka panel.iteritems()
          # just test that it works
          for k, v in self.panel.iteritems():
              pass
  
          assert len(list(self.panel.iteritems())) == len(self.panel.items)
  
      def test_combineFrame(self):
          def check_op(op, name):
              # items
              df = self.panel['ItemA']
  
              func = getattr(self.panel, name)
  
              result = func(df, axis='items')
  
              assert_frame_equal(
                  result['ItemB'], op(self.panel['ItemB'], df))
  
              # major
              xs = self.panel.major_xs(self.panel.major_axis[0])
              result = func(xs, axis='major')
  
              idx = self.panel.major_axis[1]
  
              assert_frame_equal(result.major_xs(idx),
                                 op(self.panel.major_xs(idx), xs))
  
              # minor
              xs = self.panel.minor_xs(self.panel.minor_axis[0])
              result = func(xs, axis='minor')
  
              idx = self.panel.minor_axis[1]
  
              assert_frame_equal(result.minor_xs(idx),
                                 op(self.panel.minor_xs(idx), xs))
  
          ops = ['add', 'sub', 'mul', 'truediv', 'floordiv', 'pow', 'mod']
          if not compat.PY3:
              ops.append('div')
  
          for op in ops:
              try:
                  check_op(getattr(operator, op), op)
              except:
                  pprint_thing("Failing operation: %r" % op)
                  raise
          if compat.PY3:
              try:
                  check_op(operator.truediv, 'div')
              except:
                  pprint_thing("Failing operation: %r" % 'div')
                  raise
  
      def test_combinePanel(self):
          result = self.panel.add(self.panel)
          assert_panel_equal(result, self.panel * 2)
  
      def test_neg(self):
          assert_panel_equal(-self.panel, self.panel * -1)
  
      # issue 7692
      def test_raise_when_not_implemented(self):
          p = Panel(np.arange(3 * 4 * 5).reshape(3, 4, 5),
                    items=['ItemA', 'ItemB', 'ItemC'],
                    major_axis=date_range('20130101', periods=4),
                    minor_axis=list('ABCDE'))
          d = p.sum(axis=1).iloc[0]
          ops = ['add', 'sub', 'mul', 'truediv',
                 'floordiv', 'div', 'mod', 'pow']
          for op in ops:
              with pytest.raises(NotImplementedError):
                  getattr(p, op)(d, axis=0)
  
      def test_select(self):
          p = self.panel
  
          # select items
          with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
              result = p.select(lambda x: x in ('ItemA', 'ItemC'), axis='items')
          expected = p.reindex(items=['ItemA', 'ItemC'])
          assert_panel_equal(result, expected)
  
          # select major_axis
          with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
              result = p.select(lambda x: x >= datetime(
                  2000, 1, 15), axis='major')
          new_major = p.major_axis[p.major_axis >= datetime(2000, 1, 15)]
          expected = p.reindex(major=new_major)
          assert_panel_equal(result, expected)
  
          # select minor_axis
          with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
              result = p.select(lambda x: x in ('D', 'A'), axis=2)
          expected = p.reindex(minor=['A', 'D'])
          assert_panel_equal(result, expected)
  
          # corner case, empty thing
          with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
              result = p.select(lambda x: x in ('foo', ), axis='items')
          assert_panel_equal(result, p.reindex(items=[]))
  
      def test_get_value(self):
          for item in self.panel.items:
              for mjr in self.panel.major_axis[::2]:
                  for mnr in self.panel.minor_axis:
                      with tm.assert_produces_warning(FutureWarning,
                                                      check_stacklevel=False):
                          result = self.panel.get_value(item, mjr, mnr)
                      expected = self.panel[item][mnr][mjr]
                      assert_almost_equal(result, expected)
  
      def test_abs(self):
  
          result = self.panel.abs()
          result2 = abs(self.panel)
          expected = np.abs(self.panel)
          assert_panel_equal(result, expected)
          assert_panel_equal(result2, expected)
  
          df = self.panel['ItemA']
          result = df.abs()
          result2 = abs(df)
          expected = np.abs(df)
          assert_frame_equal(result, expected)
          assert_frame_equal(result2, expected)
  
          s = df['A']
          result = s.abs()
          result2 = abs(s)
          expected = np.abs(s)
          assert_series_equal(result, expected)
          assert_series_equal(result2, expected)
          assert result.name == 'A'
          assert result2.name == 'A'
  
  
  @pytest.mark.filterwarnings("ignore:\\nPanel:FutureWarning")
  class CheckIndexing(object):
  
      def test_getitem(self):
          pytest.raises(Exception, self.panel.__getitem__, 'ItemQ')
  
      def test_delitem_and_pop(self):
          expected = self.panel['ItemA']
          result = self.panel.pop('ItemA')
          assert_frame_equal(expected, result)
          assert 'ItemA' not in self.panel.items
  
          del self.panel['ItemB']
          assert 'ItemB' not in self.panel.items
          pytest.raises(Exception, self.panel.__delitem__, 'ItemB')
  
          values = np.empty((3, 3, 3))
          values[0] = 0
          values[1] = 1
          values[2] = 2
  
          panel = Panel(values, lrange(3), lrange(3), lrange(3))
  
          # did we delete the right row?
  
          panelc = panel.copy()
          del panelc[0]
          tm.assert_frame_equal(panelc[1], panel[1])
          tm.assert_frame_equal(panelc[2], panel[2])
  
          panelc = panel.copy()
          del panelc[1]
          tm.assert_frame_equal(panelc[0], panel[0])
          tm.assert_frame_equal(panelc[2], panel[2])
  
          panelc = panel.copy()
          del panelc[2]
          tm.assert_frame_equal(panelc[1], panel[1])
          tm.assert_frame_equal(panelc[0], panel[0])
  
      def test_setitem(self):
          lp = self.panel.filter(['ItemA', 'ItemB']).to_frame()
          with pytest.raises(ValueError):
              self.panel['ItemE'] = lp
  
          # DataFrame
          df = self.panel['ItemA'][2:].filter(items=['A', 'B'])
          self.panel['ItemF'] = df
          self.panel['ItemE'] = df
  
          df2 = self.panel['ItemF']
  
          assert_frame_equal(df, df2.reindex(
              index=df.index, columns=df.columns))
  
          # scalar
          self.panel['ItemG'] = 1
          self.panel['ItemE'] = True
          assert self.panel['ItemG'].values.dtype == np.int64
          assert self.panel['ItemE'].values.dtype == np.bool_
  
          # object dtype
          self.panel['ItemQ'] = 'foo'
          assert self.panel['ItemQ'].values.dtype == np.object_
  
          # boolean dtype
          self.panel['ItemP'] = self.panel['ItemA'] > 0
          assert self.panel['ItemP'].values.dtype == np.bool_
  
          pytest.raises(TypeError, self.panel.__setitem__, 'foo',
                        self.panel.loc[['ItemP']])
  
          # bad shape
          p = Panel(np.random.randn(4, 3, 2))
          with tm.assert_raises_regex(ValueError,
                                      r"shape of value must be "
                                      r"\(3, 2\), shape of given "
                                      r"object was \(4, 2\)"):
              p[0] = np.random.randn(4, 2)
  
      def test_setitem_ndarray(self):
          timeidx = date_range(start=datetime(2009, 1, 1),
                               end=datetime(2009, 12, 31),
                               freq=MonthEnd())
          lons_coarse = np.linspace(-177.5, 177.5, 72)
          lats_coarse = np.linspace(-87.5, 87.5, 36)
          P = Panel(items=timeidx, major_axis=lons_coarse,
                    minor_axis=lats_coarse)
          data = np.random.randn(72 * 36).reshape((72, 36))
          key = datetime(2009, 2, 28)
          P[key] = data
  
          assert_almost_equal(P[key].values, data)
  
      def test_set_minor_major(self):
          # GH 11014
          df1 = DataFrame(['a', 'a', 'a', np.nan, 'a', np.nan])
          df2 = DataFrame([1.0, np.nan, 1.0, np.nan, 1.0, 1.0])
          panel = Panel({'Item1': df1, 'Item2': df2})
  
          newminor = notna(panel.iloc[:, :, 0])
          panel.loc[:, :, 'NewMinor'] = newminor
          assert_frame_equal(panel.loc[:, :, 'NewMinor'],
                             newminor.astype(object))
  
          newmajor = notna(panel.iloc[:, 0, :])
          panel.loc[:, 'NewMajor', :] = newmajor
          assert_frame_equal(panel.loc[:, 'NewMajor', :],
                             newmajor.astype(object))
  
      def test_major_xs(self):
          ref = self.panel['ItemA']
  
          idx = self.panel.major_axis[5]
          xs = self.panel.major_xs(idx)
  
          result = xs['ItemA']
          assert_series_equal(result, ref.xs(idx), check_names=False)
          assert result.name == 'ItemA'
  
          # not contained
          idx = self.panel.major_axis[0] - BDay()
          pytest.raises(Exception, self.panel.major_xs, idx)
  
      def test_major_xs_mixed(self):
          self.panel['ItemD'] = 'foo'
          xs = self.panel.major_xs(self.panel.major_axis[0])
          assert xs['ItemA'].dtype == np.float64
          assert xs['ItemD'].dtype == np.object_
  
      def test_minor_xs(self):
          ref = self.panel['ItemA']
  
          idx = self.panel.minor_axis[1]
          xs = self.panel.minor_xs(idx)
  
          assert_series_equal(xs['ItemA'], ref[idx], check_names=False)
  
          # not contained
          pytest.raises(Exception, self.panel.minor_xs, 'E')
  
      def test_minor_xs_mixed(self):
          self.panel['ItemD'] = 'foo'
  
          xs = self.panel.minor_xs('D')
          assert xs['ItemA'].dtype == np.float64
          assert xs['ItemD'].dtype == np.object_
  
      def test_xs(self):
          itemA = self.panel.xs('ItemA', axis=0)
          expected = self.panel['ItemA']
          tm.assert_frame_equal(itemA, expected)
  
          # Get a view by default.
          itemA_view = self.panel.xs('ItemA', axis=0)
          itemA_view.values[:] = np.nan
  
          assert np.isnan(self.panel['ItemA'].values).all()
  
          # Mixed-type yields a copy.
          self.panel['strings'] = 'foo'
          result = self.panel.xs('D', axis=2)
          assert result._is_copy is not None
  
      def test_getitem_fancy_labels(self):
          p = self.panel
  
          items = p.items[[1, 0]]
          dates = p.major_axis[::2]
          cols = ['D', 'C', 'F']
  
          # all 3 specified
          with catch_warnings():
              simplefilter("ignore", FutureWarning)
              # XXX: warning in _validate_read_indexer
              assert_panel_equal(p.loc[items, dates, cols],
                                 p.reindex(items=items, major=dates, minor=cols))
  
              # 2 specified
              assert_panel_equal(p.loc[:, dates, cols],
                                 p.reindex(major=dates, minor=cols))
  
              assert_panel_equal(p.loc[items, :, cols],
                                 p.reindex(items=items, minor=cols))
  
              assert_panel_equal(p.loc[items, dates, :],
                                 p.reindex(items=items, major=dates))
  
              # only 1
              assert_panel_equal(p.loc[items, :, :], p.reindex(items=items))
  
              assert_panel_equal(p.loc[:, dates, :], p.reindex(major=dates))
  
              assert_panel_equal(p.loc[:, :, cols], p.reindex(minor=cols))
  
      def test_getitem_fancy_slice(self):
          pass
  
      def test_getitem_fancy_ints(self):
          p = self.panel
  
          # #1603
          result = p.iloc[:, -1, :]
          expected = p.loc[:, p.major_axis[-1], :]
          assert_frame_equal(result, expected)
  
      def test_getitem_fancy_xs(self):
          p = self.panel
          item = 'ItemB'
  
          date = p.major_axis[5]
          col = 'C'
  
          # get DataFrame
          # item
          assert_frame_equal(p.loc[item], p[item])
          assert_frame_equal(p.loc[item, :], p[item])
          assert_frame_equal(p.loc[item, :, :], p[item])
  
          # major axis, axis=1
          assert_frame_equal(p.loc[:, date], p.major_xs(date))
          assert_frame_equal(p.loc[:, date, :], p.major_xs(date))
  
          # minor axis, axis=2
          assert_frame_equal(p.loc[:, :, 'C'], p.minor_xs('C'))
  
          # get Series
          assert_series_equal(p.loc[item, date], p[item].loc[date])
          assert_series_equal(p.loc[item, date, :], p[item].loc[date])
          assert_series_equal(p.loc[item, :, col], p[item][col])
          assert_series_equal(p.loc[:, date, col], p.major_xs(date).loc[col])
  
      def test_getitem_fancy_xs_check_view(self):
          item = 'ItemB'
          date = self.panel.major_axis[5]
  
          # make sure it's always a view
          NS = slice(None, None)
  
          # DataFrames
          comp = assert_frame_equal
          self._check_view(item, comp)
          self._check_view((item, NS), comp)
          self._check_view((item, NS, NS), comp)
          self._check_view((NS, date), comp)
          self._check_view((NS, date, NS), comp)
          self._check_view((NS, NS, 'C'), comp)
  
          # Series
          comp = assert_series_equal
          self._check_view((item, date), comp)
          self._check_view((item, date, NS), comp)
          self._check_view((item, NS, 'C'), comp)
          self._check_view((NS, date, 'C'), comp)
  
      def test_getitem_callable(self):
          p = self.panel
          # GH 12533
  
          assert_frame_equal(p[lambda x: 'ItemB'], p.loc['ItemB'])
          assert_panel_equal(p[lambda x: ['ItemB', 'ItemC']],
                             p.loc[['ItemB', 'ItemC']])
  
      def test_ix_setitem_slice_dataframe(self):
          a = Panel(items=[1, 2, 3], major_axis=[11, 22, 33],
                    minor_axis=[111, 222, 333])
          b = DataFrame(np.random.randn(2, 3), index=[111, 333],
                        columns=[1, 2, 3])
  
          a.loc[:, 22, [111, 333]] = b
  
          assert_frame_equal(a.loc[:, 22, [111, 333]], b)
  
      def test_ix_align(self):
          from pandas import Series
          b = Series(np.random.randn(10), name=0)
          b.sort_values()
          df_orig = Panel(np.random.randn(3, 10, 2))
          df = df_orig.copy()
  
          df.loc[0, :, 0] = b
          assert_series_equal(df.loc[0, :, 0].reindex(b.index), b)
  
          df = df_orig.swapaxes(0, 1)
          df.loc[:, 0, 0] = b
          assert_series_equal(df.loc[:, 0, 0].reindex(b.index), b)
  
          df = df_orig.swapaxes(1, 2)
          df.loc[0, 0, :] = b
          assert_series_equal(df.loc[0, 0, :].reindex(b.index), b)
  
      def test_ix_frame_align(self):
          p_orig = tm.makePanel()
          df = p_orig.iloc[0].copy()
          assert_frame_equal(p_orig['ItemA'], df)
  
          p = p_orig.copy()
          p.iloc[0, :, :] = df
          assert_panel_equal(p, p_orig)
  
          p = p_orig.copy()
          p.iloc[0] = df
          assert_panel_equal(p, p_orig)
  
          p = p_orig.copy()
          p.iloc[0, :, :] = df
          assert_panel_equal(p, p_orig)
  
          p = p_orig.copy()
          p.iloc[0] = df
          assert_panel_equal(p, p_orig)
  
          p = p_orig.copy()
          p.loc['ItemA'] = df
          assert_panel_equal(p, p_orig)
  
          p = p_orig.copy()
          p.loc['ItemA', :, :] = df
          assert_panel_equal(p, p_orig)
  
          p = p_orig.copy()
          p['ItemA'] = df
          assert_panel_equal(p, p_orig)
  
          p = p_orig.copy()
          p.iloc[0, [0, 1, 3, 5], -2:] = df
          out = p.iloc[0, [0, 1, 3, 5], -2:]
          assert_frame_equal(out, df.iloc[[0, 1, 3, 5], [2, 3]])
  
          # GH3830, panel assignent by values/frame
          for dtype in ['float64', 'int64']:
  
              panel = Panel(np.arange(40).reshape((2, 4, 5)),
                            items=['a1', 'a2'], dtype=dtype)
              df1 = panel.iloc[0]
              df2 = panel.iloc[1]
  
              tm.assert_frame_equal(panel.loc['a1'], df1)
              tm.assert_frame_equal(panel.loc['a2'], df2)
  
              # Assignment by Value Passes for 'a2'
              panel.loc['a2'] = df1.values
              tm.assert_frame_equal(panel.loc['a1'], df1)
              tm.assert_frame_equal(panel.loc['a2'], df1)
  
              # Assignment by DataFrame Ok w/o loc 'a2'
              panel['a2'] = df2
              tm.assert_frame_equal(panel.loc['a1'], df1)
              tm.assert_frame_equal(panel.loc['a2'], df2)
  
              # Assignment by DataFrame Fails for 'a2'
              panel.loc['a2'] = df2
              tm.assert_frame_equal(panel.loc['a1'], df1)
              tm.assert_frame_equal(panel.loc['a2'], df2)
  
      def _check_view(self, indexer, comp):
          cp = self.panel.copy()
          obj = cp.loc[indexer]
          obj.values[:] = 0
          assert (obj.values == 0).all()
          comp(cp.loc[indexer].reindex_like(obj), obj)
  
      def test_logical_with_nas(self):
          d = Panel({'ItemA': {'a': [np.nan, False]},
                     'ItemB': {'a': [True, True]}})
  
          result = d['ItemA'] | d['ItemB']
          expected = DataFrame({'a': [np.nan, True]})
          assert_frame_equal(result, expected)
  
          # this is autodowncasted here
          result = d['ItemA'].fillna(False) | d['ItemB']
          expected = DataFrame({'a': [True, True]})
          assert_frame_equal(result, expected)
  
      def test_neg(self):
          assert_panel_equal(-self.panel, -1 * self.panel)
  
      def test_invert(self):
          assert_panel_equal(-(self.panel < 0), ~(self.panel < 0))
  
      def test_comparisons(self):
          p1 = tm.makePanel()
          p2 = tm.makePanel()
  
          tp = p1.reindex(items=p1.items + ['foo'])
          df = p1[p1.items[0]]
  
          def test_comp(func):
  
              # versus same index
              result = func(p1, p2)
              tm.assert_numpy_array_equal(result.values,
                                          func(p1.values, p2.values))
  
              # versus non-indexed same objs
              pytest.raises(Exception, func, p1, tp)
  
              # versus different objs
              pytest.raises(Exception, func, p1, df)
  
              # versus scalar
              result3 = func(self.panel, 0)
              tm.assert_numpy_array_equal(result3.values,
                                          func(self.panel.values, 0))
  
          with np.errstate(invalid='ignore'):
              test_comp(operator.eq)
              test_comp(operator.ne)
              test_comp(operator.lt)
              test_comp(operator.gt)
              test_comp(operator.ge)
              test_comp(operator.le)
  
      def test_get_value(self):
          for item in self.panel.items:
              for mjr in self.panel.major_axis[::2]:
                  for mnr in self.panel.minor_axis:
                      with tm.assert_produces_warning(FutureWarning,
                                                      check_stacklevel=False):
                          result = self.panel.get_value(item, mjr, mnr)
                      expected = self.panel[item][mnr][mjr]
                      assert_almost_equal(result, expected)
          with catch_warnings():
              simplefilter("ignore", FutureWarning)
              with tm.assert_raises_regex(TypeError,
                                          "There must be an argument "
                                          "for each axis"):
                  self.panel.get_value('a')
  
      def test_set_value(self):
          for item in self.panel.items:
              for mjr in self.panel.major_axis[::2]:
                  for mnr in self.panel.minor_axis:
                      with tm.assert_produces_warning(FutureWarning,
                                                      check_stacklevel=False):
                          self.panel.set_value(item, mjr, mnr, 1.)
                      tm.assert_almost_equal(self.panel[item][mnr][mjr], 1.)
  
          # resize
          with catch_warnings():
              simplefilter("ignore", FutureWarning)
              res = self.panel.set_value('ItemE', 'foo', 'bar', 1.5)
              assert isinstance(res, Panel)
              assert res is not self.panel
              assert res.get_value('ItemE', 'foo', 'bar') == 1.5
  
              res3 = self.panel.set_value('ItemE', 'foobar', 'baz', 5)
              assert is_float_dtype(res3['ItemE'].values)
  
              msg = ("There must be an argument for each "
                     "axis plus the value provided")
              with tm.assert_raises_regex(TypeError, msg):
                  self.panel.set_value('a')
  
  
  @pytest.mark.filterwarnings("ignore:\\nPanel:FutureWarning")
  class TestPanel(PanelTests, CheckIndexing, SafeForLongAndSparse,
                  SafeForSparse):
  
      def setup_method(self, method):
          self.panel = make_test_panel()
          self.panel.major_axis.name = None
          self.panel.minor_axis.name = None
          self.panel.items.name = None
  
      def test_constructor(self):
          # with BlockManager
          wp = Panel(self.panel._data)
          assert wp._data is self.panel._data
  
          wp = Panel(self.panel._data, copy=True)
          assert wp._data is not self.panel._data
          tm.assert_panel_equal(wp, self.panel)
  
          # strings handled prop
          wp = Panel([[['foo', 'foo', 'foo', ], ['foo', 'foo', 'foo']]])
          assert wp.values.dtype == np.object_
  
          vals = self.panel.values
  
          # no copy
          wp = Panel(vals)
          assert wp.values is vals
  
          # copy
          wp = Panel(vals, copy=True)
          assert wp.values is not vals
  
          # GH #8285, test when scalar data is used to construct a Panel
          # if dtype is not passed, it should be inferred
          value_and_dtype = [(1, 'int64'), (3.14, 'float64'),
                             ('foo', np.object_)]
          for (val, dtype) in value_and_dtype:
              wp = Panel(val, items=range(2), major_axis=range(3),
                         minor_axis=range(4))
              vals = np.empty((2, 3, 4), dtype=dtype)
              vals.fill(val)
  
              tm.assert_panel_equal(wp, Panel(vals, dtype=dtype))
  
          # test the case when dtype is passed
          wp = Panel(1, items=range(2), major_axis=range(3),
                     minor_axis=range(4),
                     dtype='float32')
          vals = np.empty((2, 3, 4), dtype='float32')
          vals.fill(1)
  
          tm.assert_panel_equal(wp, Panel(vals, dtype='float32'))
  
      def test_constructor_cast(self):
          zero_filled = self.panel.fillna(0)
  
          casted = Panel(zero_filled._data, dtype=int)
          casted2 = Panel(zero_filled.values, dtype=int)
  
          exp_values = zero_filled.values.astype(int)
          assert_almost_equal(casted.values, exp_values)
          assert_almost_equal(casted2.values, exp_values)
  
          casted = Panel(zero_filled._data, dtype=np.int32)
          casted2 = Panel(zero_filled.values, dtype=np.int32)
  
          exp_values = zero_filled.values.astype(np.int32)
          assert_almost_equal(casted.values, exp_values)
          assert_almost_equal(casted2.values, exp_values)
  
          # can't cast
          data = [[['foo', 'bar', 'baz']]]
          pytest.raises(ValueError, Panel, data, dtype=float)
  
      def test_constructor_empty_panel(self):
          empty = Panel()
          assert len(empty.items) == 0
          assert len(empty.major_axis) == 0
          assert len(empty.minor_axis) == 0
  
      def test_constructor_observe_dtype(self):
          # GH #411
          panel = Panel(items=lrange(3), major_axis=lrange(3),
                        minor_axis=lrange(3), dtype='O')
          assert panel.values.dtype == np.object_
  
      def test_constructor_dtypes(self):
          # GH #797
  
          def _check_dtype(panel, dtype):
              for i in panel.items:
                  assert panel[i].values.dtype.name == dtype
  
          # only nan holding types allowed here
          for dtype in ['float64', 'float32', 'object']:
              panel = Panel(items=lrange(2), major_axis=lrange(10),
                            minor_axis=lrange(5), dtype=dtype)
              _check_dtype(panel, dtype)
  
          for dtype in ['float64', 'float32', 'int64', 'int32', 'object']:
              panel = Panel(np.array(np.random.randn(2, 10, 5), dtype=dtype),
                            items=lrange(2),
                            major_axis=lrange(10),
                            minor_axis=lrange(5), dtype=dtype)
              _check_dtype(panel, dtype)
  
          for dtype in ['float64', 'float32', 'int64', 'int32', 'object']:
              panel = Panel(np.array(np.random.randn(2, 10, 5), dtype='O'),
                            items=lrange(2),
                            major_axis=lrange(10),
                            minor_axis=lrange(5), dtype=dtype)
              _check_dtype(panel, dtype)
  
          for dtype in ['float64', 'float32', 'int64', 'int32', 'object']:
              panel = Panel(
                  np.random.randn(2, 10, 5),
                  items=lrange(2), major_axis=lrange(10),
                  minor_axis=lrange(5),
                  dtype=dtype)
              _check_dtype(panel, dtype)
  
          for dtype in ['float64', 'float32', 'int64', 'int32', 'object']:
              df1 = DataFrame(np.random.randn(2, 5),
                              index=lrange(2), columns=lrange(5))
              df2 = DataFrame(np.random.randn(2, 5),
                              index=lrange(2), columns=lrange(5))
              panel = Panel.from_dict({'a': df1, 'b': df2}, dtype=dtype)
              _check_dtype(panel, dtype)
  
      def test_constructor_fails_with_not_3d_input(self):
          with tm.assert_raises_regex(ValueError, "The number of dimensions required is 3"):  # noqa
                  Panel(np.random.randn(10, 2))
  
      def test_consolidate(self):
          assert self.panel._data.is_consolidated()
  
          self.panel['foo'] = 1.
          assert not self.panel._data.is_consolidated()
  
          panel = self.panel._consolidate()
          assert panel._data.is_consolidated()
  
      def test_ctor_dict(self):
          itema = self.panel['ItemA']
          itemb = self.panel['ItemB']
  
          d = {'A': itema, 'B': itemb[5:]}
          d2 = {'A': itema._series, 'B': itemb[5:]._series}
          d3 = {'A': None,
                'B': DataFrame(itemb[5:]._series),
                'C': DataFrame(itema._series)}
  
          wp = Panel.from_dict(d)
          wp2 = Panel.from_dict(d2)  # nested Dict
  
          # TODO: unused?
          wp3 = Panel.from_dict(d3)  # noqa
  
          tm.assert_index_equal(wp.major_axis, self.panel.major_axis)
          assert_panel_equal(wp, wp2)
  
          # intersect
          wp = Panel.from_dict(d, intersect=True)
          tm.assert_index_equal(wp.major_axis, itemb.index[5:])
  
          # use constructor
          assert_panel_equal(Panel(d), Panel.from_dict(d))
          assert_panel_equal(Panel(d2), Panel.from_dict(d2))
          assert_panel_equal(Panel(d3), Panel.from_dict(d3))
  
          # a pathological case
          d4 = {'A': None, 'B': None}
  
          # TODO: unused?
          wp4 = Panel.from_dict(d4)  # noqa
  
          assert_panel_equal(Panel(d4), Panel(items=['A', 'B']))
  
          # cast
          dcasted = {k: v.reindex(wp.major_axis).fillna(0)
                     for k, v in compat.iteritems(d)}
          result = Panel(dcasted, dtype=int)
          expected = Panel({k: v.astype(int)
                            for k, v in compat.iteritems(dcasted)})
          assert_panel_equal(result, expected)
  
          result = Panel(dcasted, dtype=np.int32)
          expected = Panel({k: v.astype(np.int32)
                            for k, v in compat.iteritems(dcasted)})
          assert_panel_equal(result, expected)
  
      def test_constructor_dict_mixed(self):
          data = {k: v.values for k, v in self.panel.iteritems()}
          result = Panel(data)
          exp_major = Index(np.arange(len(self.panel.major_axis)))
          tm.assert_index_equal(result.major_axis, exp_major)
  
          result = Panel(data, items=self.panel.items,
                         major_axis=self.panel.major_axis,
                         minor_axis=self.panel.minor_axis)
          assert_panel_equal(result, self.panel)
  
          data['ItemC'] = self.panel['ItemC']
          result = Panel(data)
          assert_panel_equal(result, self.panel)
  
          # corner, blow up
          data['ItemB'] = data['ItemB'][:-1]
          pytest.raises(Exception, Panel, data)
  
          data['ItemB'] = self.panel['ItemB'].values[:, :-1]
          pytest.raises(Exception, Panel, data)
  
      def test_ctor_orderedDict(self):
          keys = list(set(np.random.randint(0, 5000, 100)))[
              :50]  # unique random int  keys
          d = OrderedDict([(k, mkdf(10, 5)) for k in keys])
          p = Panel(d)
          assert list(p.items) == keys
  
          p = Panel.from_dict(d)
          assert list(p.items) == keys
  
      def test_constructor_resize(self):
          data = self.panel._data
          items = self.panel.items[:-1]
          major = self.panel.major_axis[:-1]
          minor = self.panel.minor_axis[:-1]
  
          result = Panel(data, items=items,
                         major_axis=major, minor_axis=minor)
          expected = self.panel.reindex(
              items=items, major=major, minor=minor)
          assert_panel_equal(result, expected)
  
          result = Panel(data, items=items, major_axis=major)
          expected = self.panel.reindex(items=items, major=major)
          assert_panel_equal(result, expected)
  
          result = Panel(data, items=items)
          expected = self.panel.reindex(items=items)
          assert_panel_equal(result, expected)
  
          result = Panel(data, minor_axis=minor)
          expected = self.panel.reindex(minor=minor)
          assert_panel_equal(result, expected)
  
      def test_from_dict_mixed_orient(self):
          df = tm.makeDataFrame()
          df['foo'] = 'bar'
  
          data = {'k1': df, 'k2': df}
  
          panel = Panel.from_dict(data, orient='minor')
  
          assert panel['foo'].values.dtype == np.object_
          assert panel['A'].values.dtype == np.float64
  
      def test_constructor_error_msgs(self):
          def testit():
              Panel(np.random.randn(3, 4, 5),
                    lrange(4), lrange(5), lrange(5))
  
          tm.assert_raises_regex(ValueError,
                                 r"Shape of passed values is "
                                 r"\(3, 4, 5\), indices imply "
                                 r"\(4, 5, 5\)",
                                 testit)
  
          def testit():
              Panel(np.random.randn(3, 4, 5),
                    lrange(5), lrange(4), lrange(5))
  
          tm.assert_raises_regex(ValueError,
                                 r"Shape of passed values is "
                                 r"\(3, 4, 5\), indices imply "
                                 r"\(5, 4, 5\)",
                                 testit)
  
          def testit():
              Panel(np.random.randn(3, 4, 5),
                    lrange(5), lrange(5), lrange(4))
  
          tm.assert_raises_regex(ValueError,
                                 r"Shape of passed values is "
                                 r"\(3, 4, 5\), indices imply "
                                 r"\(5, 5, 4\)",
                                 testit)
  
      def test_conform(self):
          df = self.panel['ItemA'][:-5].filter(items=['A', 'B'])
          conformed = self.panel.conform(df)
  
          tm.assert_index_equal(conformed.index, self.panel.major_axis)
          tm.assert_index_equal(conformed.columns, self.panel.minor_axis)
  
      def test_convert_objects(self):
          # GH 4937
          p = Panel(dict(A=dict(a=['1', '1.0'])))
          expected = Panel(dict(A=dict(a=[1, 1.0])))
          result = p._convert(numeric=True, coerce=True)
          assert_panel_equal(result, expected)
  
      def test_dtypes(self):
  
          result = self.panel.dtypes
          expected = Series(np.dtype('float64'), index=self.panel.items)
          assert_series_equal(result, expected)
  
      def test_astype(self):
          # GH7271
          data = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
          panel = Panel(data, ['a', 'b'], ['c', 'd'], ['e', 'f'])
  
          str_data = np.array([[['1', '2'], ['3', '4']],
                               [['5', '6'], ['7', '8']]])
          expected = Panel(str_data, ['a', 'b'], ['c', 'd'], ['e', 'f'])
          assert_panel_equal(panel.astype(str), expected)
  
          pytest.raises(NotImplementedError, panel.astype, {0: str})
  
      def test_apply(self):
          # GH1148
  
          # ufunc
          applied = self.panel.apply(np.sqrt)
          with np.errstate(invalid='ignore'):
              expected = np.sqrt(self.panel.values)
          assert_almost_equal(applied.values, expected)
  
          # ufunc same shape
          result = self.panel.apply(lambda x: x * 2, axis='items')
          expected = self.panel * 2
          assert_panel_equal(result, expected)
          result = self.panel.apply(lambda x: x * 2, axis='major_axis')
          expected = self.panel * 2
          assert_panel_equal(result, expected)
          result = self.panel.apply(lambda x: x * 2, axis='minor_axis')
          expected = self.panel * 2
          assert_panel_equal(result, expected)
  
          # reduction to DataFrame
          result = self.panel.apply(lambda x: x.dtype, axis='items')
          expected = DataFrame(np.dtype('float64'),
                               index=self.panel.major_axis,
                               columns=self.panel.minor_axis)
          assert_frame_equal(result, expected)
          result = self.panel.apply(lambda x: x.dtype, axis='major_axis')
          expected = DataFrame(np.dtype('float64'),
                               index=self.panel.minor_axis,
                               columns=self.panel.items)
          assert_frame_equal(result, expected)
          result = self.panel.apply(lambda x: x.dtype, axis='minor_axis')
          expected = DataFrame(np.dtype('float64'),
                               index=self.panel.major_axis,
                               columns=self.panel.items)
          assert_frame_equal(result, expected)
  
          # reductions via other dims
          expected = self.panel.sum(0)
          result = self.panel.apply(lambda x: x.sum(), axis='items')
          assert_frame_equal(result, expected)
          expected = self.panel.sum(1)
          result = self.panel.apply(lambda x: x.sum(), axis='major_axis')
          assert_frame_equal(result, expected)
          expected = self.panel.sum(2)
          result = self.panel.apply(lambda x: x.sum(), axis='minor_axis')
          assert_frame_equal(result, expected)
  
          # pass kwargs
          result = self.panel.apply(
              lambda x, y: x.sum() + y, axis='items', y=5)
          expected = self.panel.sum(0) + 5
          assert_frame_equal(result, expected)
  
      def test_apply_slabs(self):
  
          # same shape as original
          result = self.panel.apply(lambda x: x * 2,
                                    axis=['items', 'major_axis'])
          expected = (self.panel * 2).transpose('minor_axis', 'major_axis',
                                                'items')
          assert_panel_equal(result, expected)
          result = self.panel.apply(lambda x: x * 2,
                                    axis=['major_axis', 'items'])
          assert_panel_equal(result, expected)
  
          result = self.panel.apply(lambda x: x * 2,
                                    axis=['items', 'minor_axis'])
          expected = (self.panel * 2).transpose('major_axis', 'minor_axis',
                                                'items')
          assert_panel_equal(result, expected)
          result = self.panel.apply(lambda x: x * 2,
                                    axis=['minor_axis', 'items'])
          assert_panel_equal(result, expected)
  
          result = self.panel.apply(lambda x: x * 2,
                                    axis=['major_axis', 'minor_axis'])
          expected = self.panel * 2
          assert_panel_equal(result, expected)
          result = self.panel.apply(lambda x: x * 2,
                                    axis=['minor_axis', 'major_axis'])
          assert_panel_equal(result, expected)
  
          # reductions
          result = self.panel.apply(lambda x: x.sum(0), axis=[
              'items', 'major_axis'
          ])
          expected = self.panel.sum(1).T
          assert_frame_equal(result, expected)
  
          result = self.panel.apply(lambda x: x.sum(1), axis=[
              'items', 'major_axis'
          ])
          expected = self.panel.sum(0)
          assert_frame_equal(result, expected)
  
          # transforms
          f = lambda x: ((x.T - x.mean(1)) / x.std(1)).T
  
          # make sure that we don't trigger any warnings
          result = self.panel.apply(f, axis=['items', 'major_axis'])
          expected = Panel({ax: f(self.panel.loc[:, :, ax])
                            for ax in self.panel.minor_axis})
          assert_panel_equal(result, expected)
  
          result = self.panel.apply(f, axis=['major_axis', 'minor_axis'])
          expected = Panel({ax: f(self.panel.loc[ax])
                            for ax in self.panel.items})
          assert_panel_equal(result, expected)
  
          result = self.panel.apply(f, axis=['minor_axis', 'items'])
          expected = Panel({ax: f(self.panel.loc[:, ax])
                            for ax in self.panel.major_axis})
          assert_panel_equal(result, expected)
  
          # with multi-indexes
          # GH7469
          index = MultiIndex.from_tuples([('one', 'a'), ('one', 'b'), (
              'two', 'a'), ('two', 'b')])
          dfa = DataFrame(np.array(np.arange(12, dtype='int64')).reshape(
              4, 3), columns=list("ABC"), index=index)
          dfb = DataFrame(np.array(np.arange(10, 22, dtype='int64')).reshape(
              4, 3), columns=list("ABC"), index=index)
          p = Panel({'f': dfa, 'g': dfb})
          result = p.apply(lambda x: x.sum(), axis=0)
  
          # on windows this will be in32
          result = result.astype('int64')
          expected = p.sum(0)
          assert_frame_equal(result, expected)
  
      def test_apply_no_or_zero_ndim(self):
          # GH10332
          self.panel = Panel(np.random.rand(5, 5, 5))
  
          result_int = self.panel.apply(lambda df: 0, axis=[1, 2])
          result_float = self.panel.apply(lambda df: 0.0, axis=[1, 2])
          result_int64 = self.panel.apply(
              lambda df: np.int64(0), axis=[1, 2])
          result_float64 = self.panel.apply(lambda df: np.float64(0.0),
                                            axis=[1, 2])
  
          expected_int = expected_int64 = Series([0] * 5)
          expected_float = expected_float64 = Series([0.0] * 5)
  
          assert_series_equal(result_int, expected_int)
          assert_series_equal(result_int64, expected_int64)
          assert_series_equal(result_float, expected_float)
          assert_series_equal(result_float64, expected_float64)
  
      def test_reindex(self):
          ref = self.panel['ItemB']
  
          # items
          result = self.panel.reindex(items=['ItemA', 'ItemB'])
          assert_frame_equal(result['ItemB'], ref)
  
          # major
          new_major = list(self.panel.major_axis[:10])
          result = self.panel.reindex(major=new_major)
          assert_frame_equal(result['ItemB'], ref.reindex(index=new_major))
  
          # raise exception put both major and major_axis
          pytest.raises(Exception, self.panel.reindex,
                        major_axis=new_major,
                        major=new_major)
  
          # minor
          new_minor = list(self.panel.minor_axis[:2])
          result = self.panel.reindex(minor=new_minor)
          assert_frame_equal(result['ItemB'], ref.reindex(columns=new_minor))
  
          # raise exception put both major and major_axis
          pytest.raises(Exception, self.panel.reindex,
                        minor_axis=new_minor,
                        minor=new_minor)
  
          # this ok
          result = self.panel.reindex()
          assert_panel_equal(result, self.panel)
          assert result is not self.panel
  
          # with filling
          smaller_major = self.panel.major_axis[::5]
          smaller = self.panel.reindex(major=smaller_major)
  
          larger = smaller.reindex(major=self.panel.major_axis, method='pad')
  
          assert_frame_equal(larger.major_xs(self.panel.major_axis[1]),
                             smaller.major_xs(smaller_major[0]))
  
          # don't necessarily copy
          result = self.panel.reindex(
              major=self.panel.major_axis, copy=False)
          assert_panel_equal(result, self.panel)
          assert result is self.panel
  
      def test_reindex_axis_style(self):
          panel = Panel(np.random.rand(5, 5, 5))
          expected0 = Panel(panel.values).iloc[[0, 1]]
          expected1 = Panel(panel.values).iloc[:, [0, 1]]
          expected2 = Panel(panel.values).iloc[:, :, [0, 1]]
  
          result = panel.reindex([0, 1], axis=0)
          assert_panel_equal(result, expected0)
  
          result = panel.reindex([0, 1], axis=1)
          assert_panel_equal(result, expected1)
  
          result = panel.reindex([0, 1], axis=2)
          assert_panel_equal(result, expected2)
  
          result = panel.reindex([0, 1], axis=2)
          assert_panel_equal(result, expected2)
  
      def test_reindex_multi(self):
  
          # with and without copy full reindexing
          result = self.panel.reindex(
              items=self.panel.items,
              major=self.panel.major_axis,
              minor=self.panel.minor_axis, copy=False)
  
          assert result.items is self.panel.items
          assert result.major_axis is self.panel.major_axis
          assert result.minor_axis is self.panel.minor_axis
  
          result = self.panel.reindex(
              items=self.panel.items,
              major=self.panel.major_axis,
              minor=self.panel.minor_axis, copy=False)
          assert_panel_equal(result, self.panel)
  
          # multi-axis indexing consistency
          # GH 5900
          df = DataFrame(np.random.randn(4, 3))
          p = Panel({'Item1': df})
          expected = Panel({'Item1': df})
          expected['Item2'] = np.nan
  
          items = ['Item1', 'Item2']
          major_axis = np.arange(4)
          minor_axis = np.arange(3)
  
          results = []
          results.append(p.reindex(items=items, major_axis=major_axis,
                                   copy=True))
          results.append(p.reindex(items=items, major_axis=major_axis,
                                   copy=False))
          results.append(p.reindex(items=items, minor_axis=minor_axis,
                                   copy=True))
          results.append(p.reindex(items=items, minor_axis=minor_axis,
                                   copy=False))
          results.append(p.reindex(items=items, major_axis=major_axis,
                                   minor_axis=minor_axis, copy=True))
          results.append(p.reindex(items=items, major_axis=major_axis,
                                   minor_axis=minor_axis, copy=False))
  
          for i, r in enumerate(results):
              assert_panel_equal(expected, r)
  
      def test_reindex_like(self):
          # reindex_like
          smaller = self.panel.reindex(items=self.panel.items[:-1],
                                       major=self.panel.major_axis[:-1],
                                       minor=self.panel.minor_axis[:-1])
          smaller_like = self.panel.reindex_like(smaller)
          assert_panel_equal(smaller, smaller_like)
  
      def test_take(self):
          # axis == 0
          result = self.panel.take([2, 0, 1], axis=0)
          expected = self.panel.reindex(items=['ItemC', 'ItemA', 'ItemB'])
          assert_panel_equal(result, expected)
  
          # axis >= 1
          result = self.panel.take([3, 0, 1, 2], axis=2)
          expected = self.panel.reindex(minor=['D', 'A', 'B', 'C'])
          assert_panel_equal(result, expected)
  
          # neg indices ok
          expected = self.panel.reindex(minor=['D', 'D', 'B', 'C'])
          result = self.panel.take([3, -1, 1, 2], axis=2)
          assert_panel_equal(result, expected)
  
          pytest.raises(Exception, self.panel.take, [4, 0, 1, 2], axis=2)
  
      def test_sort_index(self):
          import random
  
          ritems = list(self.panel.items)
          rmajor = list(self.panel.major_axis)
          rminor = list(self.panel.minor_axis)
          random.shuffle(ritems)
          random.shuffle(rmajor)
          random.shuffle(rminor)
  
          random_order = self.panel.reindex(items=ritems)
          sorted_panel = random_order.sort_index(axis=0)
          assert_panel_equal(sorted_panel, self.panel)
  
          # descending
          random_order = self.panel.reindex(items=ritems)
          sorted_panel = random_order.sort_index(axis=0, ascending=False)
          assert_panel_equal(
              sorted_panel,
              self.panel.reindex(items=self.panel.items[::-1]))
  
          random_order = self.panel.reindex(major=rmajor)
          sorted_panel = random_order.sort_index(axis=1)
          assert_panel_equal(sorted_panel, self.panel)
  
          random_order = self.panel.reindex(minor=rminor)
          sorted_panel = random_order.sort_index(axis=2)
          assert_panel_equal(sorted_panel, self.panel)
  
      def test_fillna(self):
          filled = self.panel.fillna(0)
          assert np.isfinite(filled.values).all()
  
          filled = self.panel.fillna(method='backfill')
          assert_frame_equal(filled['ItemA'],
                             self.panel['ItemA'].fillna(method='backfill'))
  
          panel = self.panel.copy()
          panel['str'] = 'foo'
  
          filled = panel.fillna(method='backfill')
          assert_frame_equal(filled['ItemA'],
                             panel['ItemA'].fillna(method='backfill'))
  
          empty = self.panel.reindex(items=[])
          filled = empty.fillna(0)
          assert_panel_equal(filled, empty)
  
          pytest.raises(ValueError, self.panel.fillna)
          pytest.raises(ValueError, self.panel.fillna, 5, method='ffill')
  
          pytest.raises(TypeError, self.panel.fillna, [1, 2])
          pytest.raises(TypeError, self.panel.fillna, (1, 2))
  
          # limit not implemented when only value is specified
          p = Panel(np.random.randn(3, 4, 5))
          p.iloc[0:2, 0:2, 0:2] = np.nan
          pytest.raises(NotImplementedError,
                        lambda: p.fillna(999, limit=1))
  
          # Test in place fillNA
          # Expected result
          expected = Panel([[[0, 1], [2, 1]], [[10, 11], [12, 11]]],
                           items=['a', 'b'], minor_axis=['x', 'y'],
                           dtype=np.float64)
          # method='ffill'
          p1 = Panel([[[0, 1], [2, np.nan]], [[10, 11], [12, np.nan]]],
                     items=['a', 'b'], minor_axis=['x', 'y'],
                     dtype=np.float64)
          p1.fillna(method='ffill', inplace=True)
          assert_panel_equal(p1, expected)
  
          # method='bfill'
          p2 = Panel([[[0, np.nan], [2, 1]], [[10, np.nan], [12, 11]]],
                     items=['a', 'b'], minor_axis=['x', 'y'],
                     dtype=np.float64)
          p2.fillna(method='bfill', inplace=True)
          assert_panel_equal(p2, expected)
  
      def test_ffill_bfill(self):
          assert_panel_equal(self.panel.ffill(),
                             self.panel.fillna(method='ffill'))
          assert_panel_equal(self.panel.bfill(),
                             self.panel.fillna(method='bfill'))
  
      def test_truncate_fillna_bug(self):
          # #1823
          result = self.panel.truncate(before=None, after=None, axis='items')
  
          # it works!
          result.fillna(value=0.0)
  
      def test_swapaxes(self):
          result = self.panel.swapaxes('items', 'minor')
          assert result.items is self.panel.minor_axis
  
          result = self.panel.swapaxes('items', 'major')
          assert result.items is self.panel.major_axis
  
          result = self.panel.swapaxes('major', 'minor')
          assert result.major_axis is self.panel.minor_axis
  
          panel = self.panel.copy()
          result = panel.swapaxes('major', 'minor')
          panel.values[0, 0, 1] = np.nan
          expected = panel.swapaxes('major', 'minor')
          assert_panel_equal(result, expected)
  
          # this should also work
          result = self.panel.swapaxes(0, 1)
          assert result.items is self.panel.major_axis
  
          # this works, but return a copy
          result = self.panel.swapaxes('items', 'items')
          assert_panel_equal(self.panel, result)
          assert id(self.panel) != id(result)
  
      def test_transpose(self):
          result = self.panel.transpose('minor', 'major', 'items')
          expected = self.panel.swapaxes('items', 'minor')
          assert_panel_equal(result, expected)
  
          # test kwargs
          result = self.panel.transpose(items='minor', major='major',
                                        minor='items')
          expected = self.panel.swapaxes('items', 'minor')
          assert_panel_equal(result, expected)
  
          # text mixture of args
          result = self.panel.transpose(
              'minor', major='major', minor='items')
          expected = self.panel.swapaxes('items', 'minor')
          assert_panel_equal(result, expected)
  
          result = self.panel.transpose('minor',
                                        'major',
                                        minor='items')
          expected = self.panel.swapaxes('items', 'minor')
          assert_panel_equal(result, expected)
  
          # duplicate axes
          with tm.assert_raises_regex(TypeError,
                                      'not enough/duplicate arguments'):
              self.panel.transpose('minor', maj='major', minor='items')
  
          with tm.assert_raises_regex(ValueError,
                                      'repeated axis in transpose'):
              self.panel.transpose('minor', 'major', major='minor',
                                   minor='items')
  
          result = self.panel.transpose(2, 1, 0)
          assert_panel_equal(result, expected)
  
          result = self.panel.transpose('minor', 'items', 'major')
          expected = self.panel.swapaxes('items', 'minor')
          expected = expected.swapaxes('major', 'minor')
          assert_panel_equal(result, expected)
  
          result = self.panel.transpose(2, 0, 1)
          assert_panel_equal(result, expected)
  
          pytest.raises(ValueError, self.panel.transpose, 0, 0, 1)
  
      def test_transpose_copy(self):
          panel = self.panel.copy()
          result = panel.transpose(2, 0, 1, copy=True)
          expected = panel.swapaxes('items', 'minor')
          expected = expected.swapaxes('major', 'minor')
          assert_panel_equal(result, expected)
  
          panel.values[0, 1, 1] = np.nan
          assert notna(result.values[1, 0, 1])
  
      def test_to_frame(self):
          # filtered
          filtered = self.panel.to_frame()
          expected = self.panel.to_frame().dropna(how='any')
          assert_frame_equal(filtered, expected)
  
          # unfiltered
          unfiltered = self.panel.to_frame(filter_observations=False)
          assert_panel_equal(unfiltered.to_panel(), self.panel)
  
          # names
          assert unfiltered.index.names == ('major', 'minor')
  
          # unsorted, round trip
          df = self.panel.to_frame(filter_observations=False)
          unsorted = df.take(np.random.permutation(len(df)))
          pan = unsorted.to_panel()
          assert_panel_equal(pan, self.panel)
  
          # preserve original index names
          df = DataFrame(np.random.randn(6, 2),
                         index=[['a', 'a', 'b', 'b', 'c', 'c'],
                                [0, 1, 0, 1, 0, 1]],
                         columns=['one', 'two'])
          df.index.names = ['foo', 'bar']
          df.columns.name = 'baz'
  
          rdf = df.to_panel().to_frame()
          assert rdf.index.names == df.index.names
          assert rdf.columns.names == df.columns.names
  
      def test_to_frame_mixed(self):
          panel = self.panel.fillna(0)
          panel['str'] = 'foo'
          panel['bool'] = panel['ItemA'] > 0
  
          lp = panel.to_frame()
          wp = lp.to_panel()
          assert wp['bool'].values.dtype == np.bool_
          # Previously, this was mutating the underlying
          # index and changing its name
          assert_frame_equal(wp['bool'], panel['bool'], check_names=False)
  
          # GH 8704
          # with categorical
          df = panel.to_frame()
          df['category'] = df['str'].astype('category')
  
          # to_panel
          # TODO: this converts back to object
          p = df.to_panel()
          expected = panel.copy()
          expected['category'] = 'foo'
          assert_panel_equal(p, expected)
  
      def test_to_frame_multi_major(self):
          idx = MultiIndex.from_tuples(
              [(1, 'one'), (1, 'two'), (2, 'one'), (2, 'two')])
          df = DataFrame([[1, 'a', 1], [2, 'b', 1],
                          [3, 'c', 1], [4, 'd', 1]],
                         columns=['A', 'B', 'C'], index=idx)
          wp = Panel({'i1': df, 'i2': df})
          expected_idx = MultiIndex.from_tuples(
              [
                  (1, 'one', 'A'), (1, 'one', 'B'),
                  (1, 'one', 'C'), (1, 'two', 'A'),
                  (1, 'two', 'B'), (1, 'two', 'C'),
                  (2, 'one', 'A'), (2, 'one', 'B'),
                  (2, 'one', 'C'), (2, 'two', 'A'),
                  (2, 'two', 'B'), (2, 'two', 'C')
              ],
              names=[None, None, 'minor'])
          expected = DataFrame({'i1': [1, 'a', 1, 2, 'b', 1, 3,
                                       'c', 1, 4, 'd', 1],
                                'i2': [1, 'a', 1, 2, 'b',
                                       1, 3, 'c', 1, 4, 'd', 1]},
                               index=expected_idx)
          result = wp.to_frame()
          assert_frame_equal(result, expected)
  
          wp.iloc[0, 0].iloc[0] = np.nan  # BUG on setting. GH #5773
          result = wp.to_frame()
          assert_frame_equal(result, expected[1:])
  
          idx = MultiIndex.from_tuples(
              [(1, 'two'), (1, 'one'), (2, 'one'), (np.nan, 'two')])
          df = DataFrame([[1, 'a', 1], [2, 'b', 1],
                          [3, 'c', 1], [4, 'd', 1]],
                         columns=['A', 'B', 'C'], index=idx)
          wp = Panel({'i1': df, 'i2': df})
          ex_idx = MultiIndex.from_tuples([(1, 'two', 'A'), (1, 'two', 'B'),
                                           (1, 'two', 'C'),
                                           (1, 'one', 'A'),
                                           (1, 'one', 'B'),
                                           (1, 'one', 'C'),
                                           (2, 'one', 'A'),
                                           (2, 'one', 'B'),
                                           (2, 'one', 'C'),
                                           (np.nan, 'two', 'A'),
                                           (np.nan, 'two', 'B'),
                                           (np.nan, 'two', 'C')],
                                          names=[None, None, 'minor'])
          expected.index = ex_idx
          result = wp.to_frame()
          assert_frame_equal(result, expected)
  
      def test_to_frame_multi_major_minor(self):
          cols = MultiIndex(levels=[['C_A', 'C_B'], ['C_1', 'C_2']],
                            labels=[[0, 0, 1, 1], [0, 1, 0, 1]])
          idx = MultiIndex.from_tuples([(1, 'one'), (1, 'two'), (2, 'one'), (
              2, 'two'), (3, 'three'), (4, 'four')])
          df = DataFrame([[1, 2, 11, 12], [3, 4, 13, 14],
                          ['a', 'b', 'w', 'x'],
                          ['c', 'd', 'y', 'z'], [-1, -2, -3, -4],
                          [-5, -6, -7, -8]], columns=cols, index=idx)
          wp = Panel({'i1': df, 'i2': df})
  
          exp_idx = MultiIndex.from_tuples(
              [(1, 'one', 'C_A', 'C_1'), (1, 'one', 'C_A', 'C_2'),
               (1, 'one', 'C_B', 'C_1'), (1, 'one', 'C_B', 'C_2'),
               (1, 'two', 'C_A', 'C_1'), (1, 'two', 'C_A', 'C_2'),
               (1, 'two', 'C_B', 'C_1'), (1, 'two', 'C_B', 'C_2'),
               (2, 'one', 'C_A', 'C_1'), (2, 'one', 'C_A', 'C_2'),
               (2, 'one', 'C_B', 'C_1'), (2, 'one', 'C_B', 'C_2'),
               (2, 'two', 'C_A', 'C_1'), (2, 'two', 'C_A', 'C_2'),
               (2, 'two', 'C_B', 'C_1'), (2, 'two', 'C_B', 'C_2'),
               (3, 'three', 'C_A', 'C_1'), (3, 'three', 'C_A', 'C_2'),
               (3, 'three', 'C_B', 'C_1'), (3, 'three', 'C_B', 'C_2'),
               (4, 'four', 'C_A', 'C_1'), (4, 'four', 'C_A', 'C_2'),
               (4, 'four', 'C_B', 'C_1'), (4, 'four', 'C_B', 'C_2')],
              names=[None, None, None, None])
          exp_val = [[1, 1], [2, 2], [11, 11], [12, 12],
                     [3, 3], [4, 4],
                     [13, 13], [14, 14], ['a', 'a'],
                     ['b', 'b'], ['w', 'w'],
                     ['x', 'x'], ['c', 'c'], ['d', 'd'], [
                         'y', 'y'], ['z', 'z'],
                     [-1, -1], [-2, -2], [-3, -3], [-4, -4],
                     [-5, -5], [-6, -6],
                     [-7, -7], [-8, -8]]
          result = wp.to_frame()
          expected = DataFrame(exp_val, columns=['i1', 'i2'], index=exp_idx)
          assert_frame_equal(result, expected)
  
      def test_to_frame_multi_drop_level(self):
          idx = MultiIndex.from_tuples([(1, 'one'), (2, 'one'), (2, 'two')])
          df = DataFrame({'A': [np.nan, 1, 2]}, index=idx)
          wp = Panel({'i1': df, 'i2': df})
          result = wp.to_frame()
          exp_idx = MultiIndex.from_tuples(
              [(2, 'one', 'A'), (2, 'two', 'A')],
              names=[None, None, 'minor'])
          expected = DataFrame({'i1': [1., 2], 'i2': [1., 2]}, index=exp_idx)
          assert_frame_equal(result, expected)
  
      def test_to_panel_na_handling(self):
          df = DataFrame(np.random.randint(0, 10, size=20).reshape((10, 2)),
                         index=[[0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
                                [0, 1, 2, 3, 4, 5, 2, 3, 4, 5]])
  
          panel = df.to_panel()
          assert isna(panel[0].loc[1, [0, 1]]).all()
  
      def test_to_panel_duplicates(self):
          # #2441
          df = DataFrame({'a': [0, 0, 1], 'b': [1, 1, 1], 'c': [1, 2, 3]})
          idf = df.set_index(['a', 'b'])
          tm.assert_raises_regex(
              ValueError, 'non-uniquely indexed', idf.to_panel)
  
      def test_panel_dups(self):
  
          # GH 4960
          # duplicates in an index
  
          # items
          data = np.random.randn(5, 100, 5)
          no_dup_panel = Panel(data, items=list("ABCDE"))
          panel = Panel(data, items=list("AACDE"))
  
          expected = no_dup_panel['A']
          result = panel.iloc[0]
          assert_frame_equal(result, expected)
  
          expected = no_dup_panel['E']
          result = panel.loc['E']
          assert_frame_equal(result, expected)
  
          expected = no_dup_panel.loc[['A', 'B']]
          expected.items = ['A', 'A']
          result = panel.loc['A']
          assert_panel_equal(result, expected)
  
          # major
          data = np.random.randn(5, 5, 5)
          no_dup_panel = Panel(data, major_axis=list("ABCDE"))
          panel = Panel(data, major_axis=list("AACDE"))
  
          expected = no_dup_panel.loc[:, 'A']
          result = panel.iloc[:, 0]
          assert_frame_equal(result, expected)
  
          expected = no_dup_panel.loc[:, 'E']
          result = panel.loc[:, 'E']
          assert_frame_equal(result, expected)
  
          expected = no_dup_panel.loc[:, ['A', 'B']]
          expected.major_axis = ['A', 'A']
          result = panel.loc[:, 'A']
          assert_panel_equal(result, expected)
  
          # minor
          data = np.random.randn(5, 100, 5)
          no_dup_panel = Panel(data, minor_axis=list("ABCDE"))
          panel = Panel(data, minor_axis=list("AACDE"))
  
          expected = no_dup_panel.loc[:, :, 'A']
          result = panel.iloc[:, :, 0]
          assert_frame_equal(result, expected)
  
          expected = no_dup_panel.loc[:, :, 'E']
          result = panel.loc[:, :, 'E']
          assert_frame_equal(result, expected)
  
          expected = no_dup_panel.loc[:, :, ['A', 'B']]
          expected.minor_axis = ['A', 'A']
          result = panel.loc[:, :, 'A']
          assert_panel_equal(result, expected)
  
      def test_filter(self):
          pass
  
      def test_compound(self):
          compounded = self.panel.compound()
  
          assert_series_equal(compounded['ItemA'],
                              (1 + self.panel['ItemA']).product(0) - 1,
                              check_names=False)
  
      def test_shift(self):
          # major
          idx = self.panel.major_axis[0]
          idx_lag = self.panel.major_axis[1]
          shifted = self.panel.shift(1)
          assert_frame_equal(self.panel.major_xs(idx),
                             shifted.major_xs(idx_lag))
  
          # minor
          idx = self.panel.minor_axis[0]
          idx_lag = self.panel.minor_axis[1]
          shifted = self.panel.shift(1, axis='minor')
          assert_frame_equal(self.panel.minor_xs(idx),
                             shifted.minor_xs(idx_lag))
  
          # items
          idx = self.panel.items[0]
          idx_lag = self.panel.items[1]
          shifted = self.panel.shift(1, axis='items')
          assert_frame_equal(self.panel[idx], shifted[idx_lag])
  
          # negative numbers, #2164
          result = self.panel.shift(-1)
          expected = Panel({i: f.shift(-1)[:-1]
                            for i, f in self.panel.iteritems()})
          assert_panel_equal(result, expected)
  
          # mixed dtypes #6959
          data = [('item ' + ch, makeMixedDataFrame())
                  for ch in list('abcde')]
          data = dict(data)
          mixed_panel = Panel.from_dict(data, orient='minor')
          shifted = mixed_panel.shift(1)
          assert_series_equal(mixed_panel.dtypes, shifted.dtypes)
  
      def test_tshift(self):
          # PeriodIndex
          ps = tm.makePeriodPanel()
          shifted = ps.tshift(1)
          unshifted = shifted.tshift(-1)
  
          assert_panel_equal(unshifted, ps)
  
          shifted2 = ps.tshift(freq='B')
          assert_panel_equal(shifted, shifted2)
  
          shifted3 = ps.tshift(freq=BDay())
          assert_panel_equal(shifted, shifted3)
  
          tm.assert_raises_regex(ValueError, 'does not match',
                                 ps.tshift, freq='M')
  
          # DatetimeIndex
          panel = make_test_panel()
          shifted = panel.tshift(1)
          unshifted = shifted.tshift(-1)
  
          assert_panel_equal(panel, unshifted)
  
          shifted2 = panel.tshift(freq=panel.major_axis.freq)
          assert_panel_equal(shifted, shifted2)
  
          inferred_ts = Panel(panel.values, items=panel.items,
                              major_axis=Index(np.asarray(panel.major_axis)),
                              minor_axis=panel.minor_axis)
          shifted = inferred_ts.tshift(1)
          unshifted = shifted.tshift(-1)
          assert_panel_equal(shifted, panel.tshift(1))
          assert_panel_equal(unshifted, inferred_ts)
  
          no_freq = panel.iloc[:, [0, 5, 7], :]
          pytest.raises(ValueError, no_freq.tshift)
  
      def test_pct_change(self):
          df1 = DataFrame({'c1': [1, 2, 5], 'c2': [3, 4, 6]})
          df2 = df1 + 1
          df3 = DataFrame({'c1': [3, 4, 7], 'c2': [5, 6, 8]})
          wp = Panel({'i1': df1, 'i2': df2, 'i3': df3})
          # major, 1
          result = wp.pct_change()  # axis='major'
          expected = Panel({'i1': df1.pct_change(),
                            'i2': df2.pct_change(),
                            'i3': df3.pct_change()})
          assert_panel_equal(result, expected)
          result = wp.pct_change(axis=1)
          assert_panel_equal(result, expected)
          # major, 2
          result = wp.pct_change(periods=2)
          expected = Panel({'i1': df1.pct_change(2),
                            'i2': df2.pct_change(2),
                            'i3': df3.pct_change(2)})
          assert_panel_equal(result, expected)
          # minor, 1
          result = wp.pct_change(axis='minor')
          expected = Panel({'i1': df1.pct_change(axis=1),
                            'i2': df2.pct_change(axis=1),
                            'i3': df3.pct_change(axis=1)})
          assert_panel_equal(result, expected)
          result = wp.pct_change(axis=2)
          assert_panel_equal(result, expected)
          # minor, 2
          result = wp.pct_change(periods=2, axis='minor')
          expected = Panel({'i1': df1.pct_change(periods=2, axis=1),
                            'i2': df2.pct_change(periods=2, axis=1),
                            'i3': df3.pct_change(periods=2, axis=1)})
          assert_panel_equal(result, expected)
          # items, 1
          result = wp.pct_change(axis='items')
          expected = Panel(
              {'i1': DataFrame({'c1': [np.nan, np.nan, np.nan],
                                'c2': [np.nan, np.nan, np.nan]}),
               'i2': DataFrame({'c1': [1, 0.5, .2],
                                'c2': [1. / 3, 0.25, 1. / 6]}),
               'i3': DataFrame({'c1': [.5, 1. / 3, 1. / 6],
                                'c2': [.25, .2, 1. / 7]})})
          assert_panel_equal(result, expected)
          result = wp.pct_change(axis=0)
          assert_panel_equal(result, expected)
          # items, 2
          result = wp.pct_change(periods=2, axis='items')
          expected = Panel(
              {'i1': DataFrame({'c1': [np.nan, np.nan, np.nan],
                                'c2': [np.nan, np.nan, np.nan]}),
               'i2': DataFrame({'c1': [np.nan, np.nan, np.nan],
                                'c2': [np.nan, np.nan, np.nan]}),
               'i3': DataFrame({'c1': [2, 1, .4],
                                'c2': [2. / 3, .5, 1. / 3]})})
          assert_panel_equal(result, expected)
  
      def test_round(self):
          values = [[[-3.2, 2.2], [0, -4.8213], [3.123, 123.12],
                     [-1566.213, 88.88], [-12, 94.5]],
                    [[-5.82, 3.5], [6.21, -73.272], [-9.087, 23.12],
                     [272.212, -99.99], [23, -76.5]]]
          evalues = [[[float(np.around(i)) for i in j] for j in k]
                     for k in values]
          p = Panel(values, items=['Item1', 'Item2'],
                    major_axis=date_range('1/1/2000', periods=5),
                    minor_axis=['A', 'B'])
          expected = Panel(evalues, items=['Item1', 'Item2'],
                           major_axis=date_range('1/1/2000', periods=5),
                           minor_axis=['A', 'B'])
          result = p.round()
          assert_panel_equal(expected, result)
  
      def test_numpy_round(self):
          values = [[[-3.2, 2.2], [0, -4.8213], [3.123, 123.12],
                     [-1566.213, 88.88], [-12, 94.5]],
                    [[-5.82, 3.5], [6.21, -73.272], [-9.087, 23.12],
                     [272.212, -99.99], [23, -76.5]]]
          evalues = [[[float(np.around(i)) for i in j] for j in k]
                     for k in values]
          p = Panel(values, items=['Item1', 'Item2'],
                    major_axis=date_range('1/1/2000', periods=5),
                    minor_axis=['A', 'B'])
          expected = Panel(evalues, items=['Item1', 'Item2'],
                           major_axis=date_range('1/1/2000', periods=5),
                           minor_axis=['A', 'B'])
          result = np.round(p)
          assert_panel_equal(expected, result)
  
          msg = "the 'out' parameter is not supported"
          tm.assert_raises_regex(ValueError, msg, np.round, p, out=p)
  
      # removing Panel before NumPy enforces, so just ignore
      @pytest.mark.filterwarnings("ignore:Using a non-tuple:FutureWarning")
      def test_multiindex_get(self):
          ind = MultiIndex.from_tuples(
              [('a', 1), ('a', 2), ('b', 1), ('b', 2)],
              names=['first', 'second'])
          wp = Panel(np.random.random((4, 5, 5)),
                     items=ind,
                     major_axis=np.arange(5),
                     minor_axis=np.arange(5))
          f1 = wp['a']
          f2 = wp.loc['a']
          assert_panel_equal(f1, f2)
  
          assert (f1.items == [1, 2]).all()
          assert (f2.items == [1, 2]).all()
  
          MultiIndex.from_tuples([('a', 1), ('a', 2), ('b', 1)],
                                 names=['first', 'second'])
  
      @pytest.mark.filterwarnings("ignore:Using a non-tuple:FutureWarning")
      def test_multiindex_blocks(self):
          ind = MultiIndex.from_tuples([('a', 1), ('a', 2), ('b', 1)],
                                       names=['first', 'second'])
          wp = Panel(self.panel._data)
          wp.items = ind
          f1 = wp['a']
          assert (f1.items == [1, 2]).all()
  
          f1 = wp[('b', 1)]
          assert (f1.columns == ['A', 'B', 'C', 'D']).all()
  
      def test_repr_empty(self):
          empty = Panel()
          repr(empty)
  
      # ignore warning from us, because removing panel
      @pytest.mark.filterwarnings("ignore:Using:FutureWarning")
      def test_rename(self):
          mapper = {'ItemA': 'foo', 'ItemB': 'bar', 'ItemC': 'baz'}
  
          renamed = self.panel.rename(items=mapper)
          exp = Index(['foo', 'bar', 'baz'])
          tm.assert_index_equal(renamed.items, exp)
  
          renamed = self.panel.rename(minor_axis=str.lower)
          exp = Index(['a', 'b', 'c', 'd'])
          tm.assert_index_equal(renamed.minor_axis, exp)
  
          # don't copy
          renamed_nocopy = self.panel.rename(items=mapper, copy=False)
          renamed_nocopy['foo'] = 3.
          assert (self.panel['ItemA'].values == 3).all()
  
      def test_get_attr(self):
          assert_frame_equal(self.panel['ItemA'], self.panel.ItemA)
  
          # specific cases from #3440
          self.panel['a'] = self.panel['ItemA']
          assert_frame_equal(self.panel['a'], self.panel.a)
          self.panel['i'] = self.panel['ItemA']
          assert_frame_equal(self.panel['i'], self.panel.i)
  
      def test_from_frame_level1_unsorted(self):
          tuples = [('MSFT', 3), ('MSFT', 2), ('AAPL', 2), ('AAPL', 1),
                    ('MSFT', 1)]
          midx = MultiIndex.from_tuples(tuples)
          df = DataFrame(np.random.rand(5, 4), index=midx)
          p = df.to_panel()
          assert_frame_equal(p.minor_xs(2), df.xs(2, level=1).sort_index())
  
      def test_to_excel(self):
          try:
              import xlwt  # noqa
              import xlrd  # noqa
              import openpyxl  # noqa
              from pandas.io.excel import ExcelFile
          except ImportError:
              pytest.skip("need xlwt xlrd openpyxl")
  
          for ext in ['xls', 'xlsx']:
              with ensure_clean('__tmp__.' + ext) as path:
                  self.panel.to_excel(path)
                  try:
                      reader = ExcelFile(path)
                  except ImportError:
                      pytest.skip("need xlwt xlrd openpyxl")
  
                  for item, df in self.panel.iteritems():
                      recdf = reader.parse(str(item), index_col=0)
                      assert_frame_equal(df, recdf)
  
      def test_to_excel_xlsxwriter(self):
          try:
              import xlrd  # noqa
              import xlsxwriter  # noqa
              from pandas.io.excel import ExcelFile
          except ImportError:
              pytest.skip("Requires xlrd and xlsxwriter. Skipping test.")
  
          with ensure_clean('__tmp__.xlsx') as path:
              self.panel.to_excel(path, engine='xlsxwriter')
              try:
                  reader = ExcelFile(path)
              except ImportError as e:
                  pytest.skip("cannot write excel file: %s" % e)
  
              for item, df in self.panel.iteritems():
                  recdf = reader.parse(str(item), index_col=0)
                  assert_frame_equal(df, recdf)
  
      @pytest.mark.filterwarnings("ignore:'.reindex:FutureWarning")
      def test_dropna(self):
          p = Panel(np.random.randn(4, 5, 6), major_axis=list('abcde'))
          p.loc[:, ['b', 'd'], 0] = np.nan
  
          result = p.dropna(axis=1)
          exp = p.loc[:, ['a', 'c', 'e'], :]
          assert_panel_equal(result, exp)
          inp = p.copy()
          inp.dropna(axis=1, inplace=True)
          assert_panel_equal(inp, exp)
  
          result = p.dropna(axis=1, how='all')
          assert_panel_equal(result, p)
  
          p.loc[:, ['b', 'd'], :] = np.nan
          result = p.dropna(axis=1, how='all')
          exp = p.loc[:, ['a', 'c', 'e'], :]
          assert_panel_equal(result, exp)
  
          p = Panel(np.random.randn(4, 5, 6), items=list('abcd'))
          p.loc[['b'], :, 0] = np.nan
  
          result = p.dropna()
          exp = p.loc[['a', 'c', 'd']]
          assert_panel_equal(result, exp)
  
          result = p.dropna(how='all')
          assert_panel_equal(result, p)
  
          p.loc['b'] = np.nan
          result = p.dropna(how='all')
          exp = p.loc[['a', 'c', 'd']]
          assert_panel_equal(result, exp)
  
      def test_drop(self):
          df = DataFrame({"A": [1, 2], "B": [3, 4]})
          panel = Panel({"One": df, "Two": df})
  
          def check_drop(drop_val, axis_number, aliases, expected):
              try:
                  actual = panel.drop(drop_val, axis=axis_number)
                  assert_panel_equal(actual, expected)
                  for alias in aliases:
                      actual = panel.drop(drop_val, axis=alias)
                      assert_panel_equal(actual, expected)
              except AssertionError:
                  pprint_thing("Failed with axis_number %d and aliases: %s" %
                               (axis_number, aliases))
                  raise
          # Items
          expected = Panel({"One": df})
          check_drop('Two', 0, ['items'], expected)
  
          pytest.raises(KeyError, panel.drop, 'Three')
  
          # errors = 'ignore'
          dropped = panel.drop('Three', errors='ignore')
          assert_panel_equal(dropped, panel)
          dropped = panel.drop(['Two', 'Three'], errors='ignore')
          expected = Panel({"One": df})
          assert_panel_equal(dropped, expected)
  
          # Major
          exp_df = DataFrame({"A": [2], "B": [4]}, index=[1])
          expected = Panel({"One": exp_df, "Two": exp_df})
          check_drop(0, 1, ['major_axis', 'major'], expected)
  
          exp_df = DataFrame({"A": [1], "B": [3]}, index=[0])
          expected = Panel({"One": exp_df, "Two": exp_df})
          check_drop([1], 1, ['major_axis', 'major'], expected)
  
          # Minor
          exp_df = df[['B']]
          expected = Panel({"One": exp_df, "Two": exp_df})
          check_drop(["A"], 2, ['minor_axis', 'minor'], expected)
  
          exp_df = df[['A']]
          expected = Panel({"One": exp_df, "Two": exp_df})
          check_drop("B", 2, ['minor_axis', 'minor'], expected)
  
      def test_update(self):
          pan = Panel([[[1.5, np.nan, 3.], [1.5, np.nan, 3.],
                        [1.5, np.nan, 3.],
                        [1.5, np.nan, 3.]],
                       [[1.5, np.nan, 3.], [1.5, np.nan, 3.],
                        [1.5, np.nan, 3.],
                        [1.5, np.nan, 3.]]])
  
          other = Panel(
              [[[3.6, 2., np.nan], [np.nan, np.nan, 7]]], items=[1])
  
          pan.update(other)
  
          expected = Panel([[[1.5, np.nan, 3.], [1.5, np.nan, 3.],
                             [1.5, np.nan, 3.], [1.5, np.nan, 3.]],
                            [[3.6, 2., 3], [1.5, np.nan, 7],
                             [1.5, np.nan, 3.],
                             [1.5, np.nan, 3.]]])
  
          assert_panel_equal(pan, expected)
  
      def test_update_from_dict(self):
          pan = Panel({'one': DataFrame([[1.5, np.nan, 3],
                                         [1.5, np.nan, 3],
                                         [1.5, np.nan, 3.],
                                         [1.5, np.nan, 3.]]),
                       'two': DataFrame([[1.5, np.nan, 3.],
                                         [1.5, np.nan, 3.],
                                         [1.5, np.nan, 3.],
                                         [1.5, np.nan, 3.]])})
  
          other = {'two': DataFrame(
              [[3.6, 2., np.nan], [np.nan, np.nan, 7]])}
  
          pan.update(other)
  
          expected = Panel(
              {'one': DataFrame([[1.5, np.nan, 3.],
                                 [1.5, np.nan, 3.],
                                 [1.5, np.nan, 3.],
                                 [1.5, np.nan, 3.]]),
               'two': DataFrame([[3.6, 2., 3],
                                [1.5, np.nan, 7],
                                [1.5, np.nan, 3.],
                                [1.5, np.nan, 3.]])
               }
          )
  
          assert_panel_equal(pan, expected)
  
      def test_update_nooverwrite(self):
          pan = Panel([[[1.5, np.nan, 3.], [1.5, np.nan, 3.],
                        [1.5, np.nan, 3.],
                        [1.5, np.nan, 3.]],
                       [[1.5, np.nan, 3.], [1.5, np.nan, 3.],
                        [1.5, np.nan, 3.],
                        [1.5, np.nan, 3.]]])
  
          other = Panel(
              [[[3.6, 2., np.nan], [np.nan, np.nan, 7]]], items=[1])
  
          pan.update(other, overwrite=False)
  
          expected = Panel([[[1.5, np.nan, 3], [1.5, np.nan, 3],
                             [1.5, np.nan, 3.], [1.5, np.nan, 3.]],
                            [[1.5, 2., 3.], [1.5, np.nan, 3.],
                             [1.5, np.nan, 3.],
                             [1.5, np.nan, 3.]]])
  
          assert_panel_equal(pan, expected)
  
      def test_update_filtered(self):
          pan = Panel([[[1.5, np.nan, 3.], [1.5, np.nan, 3.],
                        [1.5, np.nan, 3.],
                        [1.5, np.nan, 3.]],
                       [[1.5, np.nan, 3.], [1.5, np.nan, 3.],
                        [1.5, np.nan, 3.],
                        [1.5, np.nan, 3.]]])
  
          other = Panel(
              [[[3.6, 2., np.nan], [np.nan, np.nan, 7]]], items=[1])
  
          pan.update(other, filter_func=lambda x: x > 2)
  
          expected = Panel([[[1.5, np.nan, 3.], [1.5, np.nan, 3.],
                             [1.5, np.nan, 3.], [1.5, np.nan, 3.]],
                            [[1.5, np.nan, 3], [1.5, np.nan, 7],
                             [1.5, np.nan, 3.], [1.5, np.nan, 3.]]])
  
          assert_panel_equal(pan, expected)
  
      def test_update_raise(self):
          pan = Panel([[[1.5, np.nan, 3.], [1.5, np.nan, 3.],
                        [1.5, np.nan, 3.],
                        [1.5, np.nan, 3.]],
                       [[1.5, np.nan, 3.], [1.5, np.nan, 3.],
                        [1.5, np.nan, 3.],
                        [1.5, np.nan, 3.]]])
  
          pytest.raises(Exception, pan.update, *(pan, ),
                        **{'raise_conflict': True})
  
      def test_all_any(self):
          assert (self.panel.all(axis=0).values == nanall(
              self.panel, axis=0)).all()
          assert (self.panel.all(axis=1).values == nanall(
              self.panel, axis=1).T).all()
          assert (self.panel.all(axis=2).values == nanall(
              self.panel, axis=2).T).all()
          assert (self.panel.any(axis=0).values == nanany(
              self.panel, axis=0)).all()
          assert (self.panel.any(axis=1).values == nanany(
              self.panel, axis=1).T).all()
          assert (self.panel.any(axis=2).values == nanany(
              self.panel, axis=2).T).all()
  
      def test_all_any_unhandled(self):
          pytest.raises(NotImplementedError, self.panel.all, bool_only=True)
          pytest.raises(NotImplementedError, self.panel.any, bool_only=True)
  
      # GH issue 15960
      def test_sort_values(self):
          pytest.raises(NotImplementedError, self.panel.sort_values)
          pytest.raises(NotImplementedError, self.panel.sort_values, 'ItemA')
  
  
  @pytest.mark.filterwarnings("ignore:\\nPanel:FutureWarning")
  class TestPanelFrame(object):
      """
      Check that conversions to and from Panel to DataFrame work.
      """
  
      def setup_method(self, method):
          panel = make_test_panel()
          self.panel = panel.to_frame()
          self.unfiltered_panel = panel.to_frame(filter_observations=False)
  
      def test_ops_differently_indexed(self):
          # trying to set non-identically indexed panel
          wp = self.panel.to_panel()
          wp2 = wp.reindex(major=wp.major_axis[:-1])
          lp2 = wp2.to_frame()
  
          result = self.panel + lp2
          assert_frame_equal(result.reindex(lp2.index), lp2 * 2)
  
          # careful, mutation
          self.panel['foo'] = lp2['ItemA']
          assert_series_equal(self.panel['foo'].reindex(lp2.index),
                              lp2['ItemA'],
                              check_names=False)
  
      def test_ops_scalar(self):
          result = self.panel.mul(2)
          expected = DataFrame.__mul__(self.panel, 2)
          assert_frame_equal(result, expected)
  
      def test_combineFrame(self):
          wp = self.panel.to_panel()
          result = self.panel.add(wp['ItemA'].stack(), axis=0)
          assert_frame_equal(result.to_panel()['ItemA'], wp['ItemA'] * 2)
  
      def test_combinePanel(self):
          wp = self.panel.to_panel()
          result = self.panel.add(self.panel)
          wide_result = result.to_panel()
          assert_frame_equal(wp['ItemA'] * 2, wide_result['ItemA'])
  
          # one item
          result = self.panel.add(self.panel.filter(['ItemA']))
  
      def test_combine_scalar(self):
          result = self.panel.mul(2)
          expected = DataFrame(self.panel._data) * 2
          assert_frame_equal(result, expected)
  
      def test_combine_series(self):
          s = self.panel['ItemA'][:10]
          result = self.panel.add(s, axis=0)
          expected = DataFrame.add(self.panel, s, axis=0)
          assert_frame_equal(result, expected)
  
          s = self.panel.iloc[5]
          result = self.panel + s
          expected = DataFrame.add(self.panel, s, axis=1)
          assert_frame_equal(result, expected)
  
      def test_operators(self):
          wp = self.panel.to_panel()
          result = (self.panel + 1).to_panel()
          assert_frame_equal(wp['ItemA'] + 1, result['ItemA'])
  
      def test_arith_flex_panel(self):
          ops = ['add', 'sub', 'mul', 'div',
                 'truediv', 'pow', 'floordiv', 'mod']
          if not compat.PY3:
              aliases = {}
          else:
              aliases = {'div': 'truediv'}
          self.panel = self.panel.to_panel()
  
          for n in [np.random.randint(-50, -1), np.random.randint(1, 50), 0]:
              for op in ops:
                  alias = aliases.get(op, op)
                  f = getattr(operator, alias)
                  exp = f(self.panel, n)
                  result = getattr(self.panel, op)(n)
                  assert_panel_equal(result, exp, check_panel_type=True)
  
                  # rops
                  r_f = lambda x, y: f(y, x)
                  exp = r_f(self.panel, n)
                  result = getattr(self.panel, 'r' + op)(n)
                  assert_panel_equal(result, exp)
  
      def test_sort(self):
          def is_sorted(arr):
              return (arr[1:] > arr[:-1]).any()
  
          sorted_minor = self.panel.sort_index(level=1)
          assert is_sorted(sorted_minor.index.labels[1])
  
          sorted_major = sorted_minor.sort_index(level=0)
          assert is_sorted(sorted_major.index.labels[0])
  
      def test_to_string(self):
          buf = StringIO()
          self.panel.to_string(buf)
  
      def test_to_sparse(self):
          if isinstance(self.panel, Panel):
              msg = 'sparsifying is not supported'
              tm.assert_raises_regex(NotImplementedError, msg,
                                     self.panel.to_sparse)
  
      def test_truncate(self):
          dates = self.panel.index.levels[0]
          start, end = dates[1], dates[5]
  
          trunced = self.panel.truncate(start, end).to_panel()
          expected = self.panel.to_panel()['ItemA'].truncate(start, end)
  
          # TODO truncate drops index.names
          assert_frame_equal(trunced['ItemA'], expected, check_names=False)
  
          trunced = self.panel.truncate(before=start).to_panel()
          expected = self.panel.to_panel()['ItemA'].truncate(before=start)
  
          # TODO truncate drops index.names
          assert_frame_equal(trunced['ItemA'], expected, check_names=False)
  
          trunced = self.panel.truncate(after=end).to_panel()
          expected = self.panel.to_panel()['ItemA'].truncate(after=end)
  
          # TODO truncate drops index.names
          assert_frame_equal(trunced['ItemA'], expected, check_names=False)
  
          # truncate on dates that aren't in there
          wp = self.panel.to_panel()
          new_index = wp.major_axis[::5]
  
          wp2 = wp.reindex(major=new_index)
  
          lp2 = wp2.to_frame()
          lp_trunc = lp2.truncate(wp.major_axis[2], wp.major_axis[-2])
  
          wp_trunc = wp2.truncate(wp.major_axis[2], wp.major_axis[-2])
  
          assert_panel_equal(wp_trunc, lp_trunc.to_panel())
  
          # throw proper exception
          pytest.raises(Exception, lp2.truncate, wp.major_axis[-2],
                        wp.major_axis[2])
  
      def test_axis_dummies(self):
          from pandas.core.reshape.reshape import make_axis_dummies
  
          minor_dummies = make_axis_dummies(self.panel, 'minor').astype(np.uint8)
          assert len(minor_dummies.columns) == len(self.panel.index.levels[1])
  
          major_dummies = make_axis_dummies(self.panel, 'major').astype(np.uint8)
          assert len(major_dummies.columns) == len(self.panel.index.levels[0])
  
          mapping = {'A': 'one', 'B': 'one', 'C': 'two', 'D': 'two'}
  
          transformed = make_axis_dummies(self.panel, 'minor',
                                          transform=mapping.get).astype(np.uint8)
          assert len(transformed.columns) == 2
          tm.assert_index_equal(transformed.columns, Index(['one', 'two']))
  
          # TODO: test correctness
  
      def test_get_dummies(self):
          from pandas.core.reshape.reshape import get_dummies, make_axis_dummies
  
          self.panel['Label'] = self.panel.index.labels[1]
          minor_dummies = make_axis_dummies(self.panel, 'minor').astype(np.uint8)
          dummies = get_dummies(self.panel['Label'])
          tm.assert_numpy_array_equal(dummies.values, minor_dummies.values)
  
      def test_mean(self):
          means = self.panel.mean(level='minor')
  
          # test versus Panel version
          wide_means = self.panel.to_panel().mean('major')
          assert_frame_equal(means, wide_means)
  
      def test_sum(self):
          sums = self.panel.sum(level='minor')
  
          # test versus Panel version
          wide_sums = self.panel.to_panel().sum('major')
          assert_frame_equal(sums, wide_sums)
  
      def test_count(self):
          index = self.panel.index
  
          major_count = self.panel.count(level=0)['ItemA']
          labels = index.labels[0]
          for i, idx in enumerate(index.levels[0]):
              assert major_count[i] == (labels == i).sum()
  
          minor_count = self.panel.count(level=1)['ItemA']
          labels = index.labels[1]
          for i, idx in enumerate(index.levels[1]):
              assert minor_count[i] == (labels == i).sum()
  
      def test_join(self):
          lp1 = self.panel.filter(['ItemA', 'ItemB'])
          lp2 = self.panel.filter(['ItemC'])
  
          joined = lp1.join(lp2)
  
          assert len(joined.columns) == 3
  
          pytest.raises(Exception, lp1.join,
                        self.panel.filter(['ItemB', 'ItemC']))
  
  
  def test_panel_index():
      index = panelm.panel_index([1, 2, 3, 4], [1, 2, 3])
      expected = MultiIndex.from_arrays([np.tile([1, 2, 3, 4], 3),
                                         np.repeat([1, 2, 3], 4)],
                                        names=['time', 'panel'])
      tm.assert_index_equal(index, expected)
  
  
  @pytest.mark.filterwarnings("ignore:\\nPanel:FutureWarning")
  def test_panel_np_all():
      wp = Panel({"A": DataFrame({'b': [1, 2]})})
      result = np.all(wp)
      assert result == np.bool_(True)
  