code: # -*- coding: utf-8 -*-
  from __future__ import print_function
  
  import re
  import sys
  from datetime import datetime, timedelta
  
  import numpy as np
  
  import pandas as pd
  import pandas.compat as compat
  from pandas.types.common import (is_object_dtype, is_datetimetz,
                                   needs_i8_conversion)
  import pandas.util.testing as tm
  from pandas import (Series, Index, DatetimeIndex, TimedeltaIndex, PeriodIndex,
                      Timedelta)
  from pandas.compat import u, StringIO
  from pandas.compat.numpy import np_array_datetime64_compat
  from pandas.core.base import (FrozenList, FrozenNDArray, PandasDelegate,
                                NoNewAttributesMixin)
  from pandas.tseries.base import DatetimeIndexOpsMixin
  
  
  class CheckStringMixin(object):
  
      def test_string_methods_dont_fail(self):
          repr(self.container)
          str(self.container)
          bytes(self.container)
          if not compat.PY3:
              unicode(self.container)  # noqa
  
      def test_tricky_container(self):
          if not hasattr(self, 'unicode_container'):
              raise nose.SkipTest('Need unicode_container to test with this')
          repr(self.unicode_container)
          str(self.unicode_container)
          bytes(self.unicode_container)
          if not compat.PY3:
              unicode(self.unicode_container)  # noqa
  
  
  class CheckImmutable(object):
      mutable_regex = re.compile('does not support mutable operations')
  
      def check_mutable_error(self, *args, **kwargs):
          # pass whatever functions you normally would to assertRaises (after the
          # Exception kind)
          tm.assertRaisesRegexp(TypeError, self.mutable_regex, *args, **kwargs)
  
      def test_no_mutable_funcs(self):
          def setitem():
              self.container[0] = 5
  
          self.check_mutable_error(setitem)
  
          def setslice():
              self.container[1:2] = 3
  
          self.check_mutable_error(setslice)
  
          def delitem():
              del self.container[0]
  
          self.check_mutable_error(delitem)
  
          def delslice():
              del self.container[0:3]
  
          self.check_mutable_error(delslice)
          mutable_methods = getattr(self, "mutable_methods", [])
          for meth in mutable_methods:
              self.check_mutable_error(getattr(self.container, meth))
  
      def test_slicing_maintains_type(self):
          result = self.container[1:2]
          expected = self.lst[1:2]
          self.check_result(result, expected)
  
      def check_result(self, result, expected, klass=None):
          klass = klass or self.klass
          self.assertIsInstance(result, klass)
          self.assertEqual(result, expected)
  
  
  class TestFrozenList(CheckImmutable, CheckStringMixin, tm.TestCase):
      mutable_methods = ('extend', 'pop', 'remove', 'insert')
      unicode_container = FrozenList([u("\u05d0"), u("\u05d1"), "c"])
  
      def setUp(self):
          self.lst = [1, 2, 3, 4, 5]
          self.container = FrozenList(self.lst)
          self.klass = FrozenList
  
      def test_add(self):
          result = self.container + (1, 2, 3)
          expected = FrozenList(self.lst + [1, 2, 3])
          self.check_result(result, expected)
  
          result = (1, 2, 3) + self.container
          expected = FrozenList([1, 2, 3] + self.lst)
          self.check_result(result, expected)
  
      def test_inplace(self):
          q = r = self.container
          q += [5]
          self.check_result(q, self.lst + [5])
          # other shouldn't be mutated
          self.check_result(r, self.lst)
  
  
  class TestFrozenNDArray(CheckImmutable, CheckStringMixin, tm.TestCase):
      mutable_methods = ('put', 'itemset', 'fill')
      unicode_container = FrozenNDArray([u("\u05d0"), u("\u05d1"), "c"])
  
      def setUp(self):
          self.lst = [3, 5, 7, -2]
          self.container = FrozenNDArray(self.lst)
          self.klass = FrozenNDArray
  
      def test_shallow_copying(self):
          original = self.container.copy()
          self.assertIsInstance(self.container.view(), FrozenNDArray)
          self.assertFalse(isinstance(
              self.container.view(np.ndarray), FrozenNDArray))
          self.assertIsNot(self.container.view(), self.container)
          self.assert_numpy_array_equal(self.container, original)
          # shallow copy should be the same too
          self.assertIsInstance(self.container._shallow_copy(), FrozenNDArray)
  
          # setting should not be allowed
          def testit(container):
              container[0] = 16
  
          self.check_mutable_error(testit, self.container)
  
      def test_values(self):
          original = self.container.view(np.ndarray).copy()
          n = original[0] + 15
          vals = self.container.values()
          self.assert_numpy_array_equal(original, vals)
          self.assertIsNot(original, vals)
          vals[0] = n
          self.assertIsInstance(self.container, pd.core.base.FrozenNDArray)
          self.assert_numpy_array_equal(self.container.values(), original)
          self.assertEqual(vals[0], n)
  
  
  class TestPandasDelegate(tm.TestCase):
  
      class Delegator(object):
          _properties = ['foo']
          _methods = ['bar']
  
          def _set_foo(self, value):
              self.foo = value
  
          def _get_foo(self):
              return self.foo
  
          foo = property(_get_foo, _set_foo, doc="foo property")
  
          def bar(self, *args, **kwargs):
              """ a test bar method """
              pass
  
      class Delegate(PandasDelegate):
  
          def __init__(self, obj):
              self.obj = obj
  
      def setUp(self):
          pass
  
      def test_invalida_delgation(self):
          # these show that in order for the delegation to work
          # the _delegate_* methods need to be overriden to not raise a TypeError
  
          self.Delegate._add_delegate_accessors(
              delegate=self.Delegator,
              accessors=self.Delegator._properties,
              typ='property'
          )
          self.Delegate._add_delegate_accessors(
              delegate=self.Delegator,
              accessors=self.Delegator._methods,
              typ='method'
          )
  
          delegate = self.Delegate(self.Delegator())
  
          def f():
              delegate.foo
  
          self.assertRaises(TypeError, f)
  
          def f():
              delegate.foo = 5
  
          self.assertRaises(TypeError, f)
  
          def f():
              delegate.foo()
  
          self.assertRaises(TypeError, f)
  
      def test_memory_usage(self):
          # Delegate does not implement memory_usage.
          # Check that we fall back to in-built `__sizeof__`
          # GH 12924
          delegate = self.Delegate(self.Delegator())
          sys.getsizeof(delegate)
  
  
  class Ops(tm.TestCase):
  
      def _allow_na_ops(self, obj):
          """Whether to skip test cases including NaN"""
          if (isinstance(obj, Index) and
                  (obj.is_boolean() or not obj._can_hold_na)):
              # don't test boolean / int64 index
              return False
          return True
  
      def setUp(self):
          self.bool_index = tm.makeBoolIndex(10, name='a')
          self.int_index = tm.makeIntIndex(10, name='a')
          self.float_index = tm.makeFloatIndex(10, name='a')
          self.dt_index = tm.makeDateIndex(10, name='a')
          self.dt_tz_index = tm.makeDateIndex(10, name='a').tz_localize(
              tz='US/Eastern')
          self.period_index = tm.makePeriodIndex(10, name='a')
          self.string_index = tm.makeStringIndex(10, name='a')
          self.unicode_index = tm.makeUnicodeIndex(10, name='a')
  
          arr = np.random.randn(10)
          self.int_series = Series(arr, index=self.int_index, name='a')
          self.float_series = Series(arr, index=self.float_index, name='a')
          self.dt_series = Series(arr, index=self.dt_index, name='a')
          self.dt_tz_series = self.dt_tz_index.to_series(keep_tz=True)
          self.period_series = Series(arr, index=self.period_index, name='a')
          self.string_series = Series(arr, index=self.string_index, name='a')
  
          types = ['bool', 'int', 'float', 'dt', 'dt_tz', 'period', 'string',
                   'unicode']
          fmts = ["{0}_{1}".format(t, f)
                  for t in types for f in ['index', 'series']]
          self.objs = [getattr(self, f)
                       for f in fmts if getattr(self, f, None) is not None]
  
      def check_ops_properties(self, props, filter=None, ignore_failures=False):
          for op in props:
              for o in self.is_valid_objs:
  
                  # if a filter, skip if it doesn't match
                  if filter is not None:
                      filt = o.index if isinstance(o, Series) else o
                      if not filter(filt):
                          continue
  
                  try:
                      if isinstance(o, Series):
                          expected = Series(
                              getattr(o.index, op), index=o.index, name='a')
                      else:
                          expected = getattr(o, op)
                  except (AttributeError):
                      if ignore_failures:
                          continue
  
                  result = getattr(o, op)
  
                  # these couuld be series, arrays or scalars
                  if isinstance(result, Series) and isinstance(expected, Series):
                      tm.assert_series_equal(result, expected)
                  elif isinstance(result, Index) and isinstance(expected, Index):
                      tm.assert_index_equal(result, expected)
                  elif isinstance(result, np.ndarray) and isinstance(expected,
                                                                     np.ndarray):
                      self.assert_numpy_array_equal(result, expected)
                  else:
                      self.assertEqual(result, expected)
  
              # freq raises AttributeError on an Int64Index because its not
              # defined we mostly care about Series hwere anyhow
              if not ignore_failures:
                  for o in self.not_valid_objs:
  
                      # an object that is datetimelike will raise a TypeError,
                      # otherwise an AttributeError
                      if issubclass(type(o), DatetimeIndexOpsMixin):
                          self.assertRaises(TypeError, lambda: getattr(o, op))
                      else:
                          self.assertRaises(AttributeError,
                                            lambda: getattr(o, op))
  
      def test_binary_ops_docs(self):
          from pandas import DataFrame, Panel
          op_map = {'add': '+',
                    'sub': '-',
                    'mul': '*',
                    'mod': '%',
                    'pow': '**',
                    'truediv': '/',
                    'floordiv': '//'}
          for op_name in ['add', 'sub', 'mul', 'mod', 'pow', 'truediv',
                          'floordiv']:
              for klass in [Series, DataFrame, Panel]:
                  operand1 = klass.__name__.lower()
                  operand2 = 'other'
                  op = op_map[op_name]
                  expected_str = ' '.join([operand1, op, operand2])
                  self.assertTrue(expected_str in getattr(klass,
                                                          op_name).__doc__)
  
                  # reverse version of the binary ops
                  expected_str = ' '.join([operand2, op, operand1])
                  self.assertTrue(expected_str in getattr(klass, 'r' +
                                                          op_name).__doc__)
  
  
  class TestIndexOps(Ops):
  
      def setUp(self):
          super(TestIndexOps, self).setUp()
          self.is_valid_objs = [o for o in self.objs if o._allow_index_ops]
          self.not_valid_objs = [o for o in self.objs if not o._allow_index_ops]
  
      def test_none_comparison(self):
  
          # bug brought up by #1079
          # changed from TypeError in 0.17.0
          for o in self.is_valid_objs:
              if isinstance(o, Series):
  
                  o[0] = np.nan
  
                  # noinspection PyComparisonWithNone
                  result = o == None  # noqa
                  self.assertFalse(result.iat[0])
                  self.assertFalse(result.iat[1])
  
                  # noinspection PyComparisonWithNone
                  result = o != None  # noqa
                  self.assertTrue(result.iat[0])
                  self.assertTrue(result.iat[1])
  
                  result = None == o  # noqa
                  self.assertFalse(result.iat[0])
                  self.assertFalse(result.iat[1])
  
                  # this fails for numpy < 1.9
                  # and oddly for *some* platforms
                  # result = None != o  # noqa
                  # self.assertTrue(result.iat[0])
                  # self.assertTrue(result.iat[1])
  
                  result = None > o
                  self.assertFalse(result.iat[0])
                  self.assertFalse(result.iat[1])
  
                  result = o < None
                  self.assertFalse(result.iat[0])
                  self.assertFalse(result.iat[1])
  
      def test_ndarray_compat_properties(self):
  
          for o in self.objs:
  
              # check that we work
              for p in ['shape', 'dtype', 'flags', 'T', 'strides', 'itemsize',
                        'nbytes']:
                  self.assertIsNotNone(getattr(o, p, None))
              self.assertTrue(hasattr(o, 'base'))
  
              # if we have a datetimelike dtype then needs a view to work
              # but the user is responsible for that
              try:
                  self.assertIsNotNone(o.data)
              except ValueError:
                  pass
  
              self.assertRaises(ValueError, o.item)  # len > 1
              self.assertEqual(o.ndim, 1)
              self.assertEqual(o.size, len(o))
  
          self.assertEqual(Index([1]).item(), 1)
          self.assertEqual(Series([1]).item(), 1)
  
      def test_ops(self):
          for op in ['max', 'min']:
              for o in self.objs:
                  result = getattr(o, op)()
                  if not isinstance(o, PeriodIndex):
                      expected = getattr(o.values, op)()
                  else:
                      expected = pd.Period(ordinal=getattr(o._values, op)(),
                                           freq=o.freq)
                  try:
                      self.assertEqual(result, expected)
                  except TypeError:
                      # comparing tz-aware series with np.array results in
                      # TypeError
                      expected = expected.astype('M8[ns]').astype('int64')
                      self.assertEqual(result.value, expected)
  
      def test_nanops(self):
          # GH 7261
          for op in ['max', 'min']:
              for klass in [Index, Series]:
  
                  obj = klass([np.nan, 2.0])
                  self.assertEqual(getattr(obj, op)(), 2.0)
  
                  obj = klass([np.nan])
                  self.assertTrue(pd.isnull(getattr(obj, op)()))
  
                  obj = klass([])
                  self.assertTrue(pd.isnull(getattr(obj, op)()))
  
                  obj = klass([pd.NaT, datetime(2011, 11, 1)])
                  # check DatetimeIndex monotonic path
                  self.assertEqual(getattr(obj, op)(), datetime(2011, 11, 1))
  
                  obj = klass([pd.NaT, datetime(2011, 11, 1), pd.NaT])
                  # check DatetimeIndex non-monotonic path
                  self.assertEqual(getattr(obj, op)(), datetime(2011, 11, 1))
  
          # argmin/max
          obj = Index(np.arange(5, dtype='int64'))
          self.assertEqual(obj.argmin(), 0)
          self.assertEqual(obj.argmax(), 4)
  
          obj = Index([np.nan, 1, np.nan, 2])
          self.assertEqual(obj.argmin(), 1)
          self.assertEqual(obj.argmax(), 3)
  
          obj = Index([np.nan])
          self.assertEqual(obj.argmin(), -1)
          self.assertEqual(obj.argmax(), -1)
  
          obj = Index([pd.NaT, datetime(2011, 11, 1), datetime(2011, 11, 2),
                       pd.NaT])
          self.assertEqual(obj.argmin(), 1)
          self.assertEqual(obj.argmax(), 2)
  
          obj = Index([pd.NaT])
          self.assertEqual(obj.argmin(), -1)
          self.assertEqual(obj.argmax(), -1)
  
      def test_value_counts_unique_nunique(self):
          for orig in self.objs:
              o = orig.copy()
              klass = type(o)
              values = o._values
  
              if isinstance(values, Index):
                  # reset name not to affect latter process
                  values.name = None
  
              # create repeated values, 'n'th element is repeated by n+1 times
              # skip boolean, because it only has 2 values at most
              if isinstance(o, Index) and o.is_boolean():
                  continue
              elif isinstance(o, Index):
                  expected_index = pd.Index(o[::-1])
                  expected_index.name = None
                  o = o.repeat(range(1, len(o) + 1))
                  o.name = 'a'
              else:
                  expected_index = pd.Index(values[::-1])
                  idx = o.index.repeat(range(1, len(o) + 1))
                  rep = np.repeat(values, range(1, len(o) + 1))
                  o = klass(rep, index=idx, name='a')
  
              # check values has the same dtype as the original
              self.assertEqual(o.dtype, orig.dtype)
  
              expected_s = Series(range(10, 0, -1), index=expected_index,
                                  dtype='int64', name='a')
  
              result = o.value_counts()
              tm.assert_series_equal(result, expected_s)
              self.assertTrue(result.index.name is None)
              self.assertEqual(result.name, 'a')
  
              result = o.unique()
              if isinstance(o, Index):
                  self.assertTrue(isinstance(result, o.__class__))
                  self.assert_index_equal(result, orig)
              elif is_datetimetz(o):
                  # datetimetz Series returns array of Timestamp
                  self.assertEqual(result[0], orig[0])
                  for r in result:
                      self.assertIsInstance(r, pd.Timestamp)
                  tm.assert_numpy_array_equal(result,
                                              orig._values.asobject.values)
              else:
                  tm.assert_numpy_array_equal(result, orig.values)
  
              self.assertEqual(o.nunique(), len(np.unique(o.values)))
  
      def test_value_counts_unique_nunique_null(self):
  
          for null_obj in [np.nan, None]:
              for orig in self.objs:
                  o = orig.copy()
                  klass = type(o)
                  values = o._values
  
                  if not self._allow_na_ops(o):
                      continue
  
                  # special assign to the numpy array
                  if is_datetimetz(o):
                      if isinstance(o, DatetimeIndex):
                          v = o.asi8
                          v[0:2] = pd.tslib.iNaT
                          values = o._shallow_copy(v)
                      else:
                          o = o.copy()
                          o[0:2] = pd.tslib.iNaT
                          values = o._values
  
                  elif needs_i8_conversion(o):
                      values[0:2] = pd.tslib.iNaT
                      values = o._shallow_copy(values)
                  else:
                      values[0:2] = null_obj
                  # check values has the same dtype as the original
  
                  self.assertEqual(values.dtype, o.dtype)
  
                  # create repeated values, 'n'th element is repeated by n+1
                  # times
                  if isinstance(o, (DatetimeIndex, PeriodIndex)):
                      expected_index = o.copy()
                      expected_index.name = None
  
                      # attach name to klass
                      o = klass(values.repeat(range(1, len(o) + 1)))
                      o.name = 'a'
                  else:
                      if is_datetimetz(o):
                          expected_index = orig._values._shallow_copy(values)
                      else:
                          expected_index = pd.Index(values)
                      expected_index.name = None
                      o = o.repeat(range(1, len(o) + 1))
                      o.name = 'a'
  
                  # check values has the same dtype as the original
                  self.assertEqual(o.dtype, orig.dtype)
                  # check values correctly have NaN
                  nanloc = np.zeros(len(o), dtype=np.bool)
                  nanloc[:3] = True
                  if isinstance(o, Index):
                      self.assert_numpy_array_equal(pd.isnull(o), nanloc)
                  else:
                      exp = pd.Series(nanloc, o.index, name='a')
                      self.assert_series_equal(pd.isnull(o), exp)
  
                  expected_s_na = Series(list(range(10, 2, -1)) + [3],
                                         index=expected_index[9:0:-1],
                                         dtype='int64', name='a')
                  expected_s = Series(list(range(10, 2, -1)),
                                      index=expected_index[9:1:-1],
                                      dtype='int64', name='a')
  
                  result_s_na = o.value_counts(dropna=False)
                  tm.assert_series_equal(result_s_na, expected_s_na)
                  self.assertTrue(result_s_na.index.name is None)
                  self.assertEqual(result_s_na.name, 'a')
                  result_s = o.value_counts()
                  tm.assert_series_equal(o.value_counts(), expected_s)
                  self.assertTrue(result_s.index.name is None)
                  self.assertEqual(result_s.name, 'a')
  
                  result = o.unique()
                  if isinstance(o, Index):
                      tm.assert_index_equal(result,
                                            Index(values[1:], name='a'))
                  elif is_datetimetz(o):
                      # unable to compare NaT / nan
                      tm.assert_numpy_array_equal(result[1:],
                                                  values[2:].asobject.values)
                      self.assertIs(result[0], pd.NaT)
                  else:
                      tm.assert_numpy_array_equal(result[1:], values[2:])
  
                      self.assertTrue(pd.isnull(result[0]))
                      self.assertEqual(result.dtype, orig.dtype)
  
                  self.assertEqual(o.nunique(), 8)
                  self.assertEqual(o.nunique(dropna=False), 9)
  
      def test_value_counts_inferred(self):
          klasses = [Index, Series]
          for klass in klasses:
              s_values = ['a', 'b', 'b', 'b', 'b', 'c', 'd', 'd', 'a', 'a']
              s = klass(s_values)
              expected = Series([4, 3, 2, 1], index=['b', 'a', 'd', 'c'])
              tm.assert_series_equal(s.value_counts(), expected)
  
              if isinstance(s, Index):
                  exp = Index(np.unique(np.array(s_values, dtype=np.object_)))
                  tm.assert_index_equal(s.unique(), exp)
              else:
                  exp = np.unique(np.array(s_values, dtype=np.object_))
                  tm.assert_numpy_array_equal(s.unique(), exp)
  
              self.assertEqual(s.nunique(), 4)
              # don't sort, have to sort after the fact as not sorting is
              # platform-dep
              hist = s.value_counts(sort=False).sort_values()
              expected = Series([3, 1, 4, 2], index=list('acbd')).sort_values()
              tm.assert_series_equal(hist, expected)
  
              # sort ascending
              hist = s.value_counts(ascending=True)
              expected = Series([1, 2, 3, 4], index=list('cdab'))
              tm.assert_series_equal(hist, expected)
  
              # relative histogram.
              hist = s.value_counts(normalize=True)
              expected = Series([.4, .3, .2, .1], index=['b', 'a', 'd', 'c'])
              tm.assert_series_equal(hist, expected)
  
      def test_value_counts_bins(self):
          klasses = [Index, Series]
          for klass in klasses:
              s_values = ['a', 'b', 'b', 'b', 'b', 'c', 'd', 'd', 'a', 'a']
              s = klass(s_values)
  
              # bins
              self.assertRaises(TypeError,
                                lambda bins: s.value_counts(bins=bins), 1)
  
              s1 = Series([1, 1, 2, 3])
              res1 = s1.value_counts(bins=1)
              exp1 = Series({0.998: 4})
              tm.assert_series_equal(res1, exp1)
              res1n = s1.value_counts(bins=1, normalize=True)
              exp1n = Series({0.998: 1.0})
              tm.assert_series_equal(res1n, exp1n)
  
              if isinstance(s1, Index):
                  tm.assert_index_equal(s1.unique(), Index([1, 2, 3]))
              else:
                  exp = np.array([1, 2, 3], dtype=np.int64)
                  tm.assert_numpy_array_equal(s1.unique(), exp)
  
              self.assertEqual(s1.nunique(), 3)
  
              res4 = s1.value_counts(bins=4)
              exp4 = Series({0.998: 2,
                             1.5: 1,
                             2.0: 0,
                             2.5: 1}, index=[0.998, 2.5, 1.5, 2.0])
              tm.assert_series_equal(res4, exp4)
              res4n = s1.value_counts(bins=4, normalize=True)
              exp4n = Series(
                  {0.998: 0.5,
                   1.5: 0.25,
                   2.0: 0.0,
                   2.5: 0.25}, index=[0.998, 2.5, 1.5, 2.0])
              tm.assert_series_equal(res4n, exp4n)
  
              # handle NA's properly
              s_values = ['a', 'b', 'b', 'b', np.nan, np.nan,
                          'd', 'd', 'a', 'a', 'b']
              s = klass(s_values)
              expected = Series([4, 3, 2], index=['b', 'a', 'd'])
              tm.assert_series_equal(s.value_counts(), expected)
  
              if isinstance(s, Index):
                  exp = Index(['a', 'b', np.nan, 'd'])
                  tm.assert_index_equal(s.unique(), exp)
              else:
                  exp = np.array(['a', 'b', np.nan, 'd'], dtype=object)
                  tm.assert_numpy_array_equal(s.unique(), exp)
              self.assertEqual(s.nunique(), 3)
  
              s = klass({})
              expected = Series([], dtype=np.int64)
              tm.assert_series_equal(s.value_counts(), expected,
                                     check_index_type=False)
              # returned dtype differs depending on original
              if isinstance(s, Index):
                  self.assert_index_equal(s.unique(), Index([]),
                                          exact=False)
              else:
                  self.assert_numpy_array_equal(s.unique(), np.array([]),
                                                check_dtype=False)
  
              self.assertEqual(s.nunique(), 0)
  
      def test_value_counts_datetime64(self):
          klasses = [Index, Series]
          for klass in klasses:
              # GH 3002, datetime64[ns]
              # don't test names though
              txt = "\n".join(['xxyyzz20100101PIE', 'xxyyzz20100101GUM',
                               'xxyyzz20100101EGG', 'xxyyww20090101EGG',
                               'foofoo20080909PIE', 'foofoo20080909GUM'])
              f = StringIO(txt)
              df = pd.read_fwf(f, widths=[6, 8, 3],
                               names=["person_id", "dt", "food"],
                               parse_dates=["dt"])
  
              s = klass(df['dt'].copy())
              s.name = None
  
              idx = pd.to_datetime(['2010-01-01 00:00:00Z',
                                    '2008-09-09 00:00:00Z',
                                    '2009-01-01 00:00:00X'])
              expected_s = Series([3, 2, 1], index=idx)
              tm.assert_series_equal(s.value_counts(), expected_s)
  
              expected = np_array_datetime64_compat(['2010-01-01 00:00:00Z',
                                                     '2009-01-01 00:00:00Z',
                                                     '2008-09-09 00:00:00Z'],
                                                    dtype='datetime64[ns]')
              if isinstance(s, Index):
                  tm.assert_index_equal(s.unique(), DatetimeIndex(expected))
              else:
                  tm.assert_numpy_array_equal(s.unique(), expected)
  
              self.assertEqual(s.nunique(), 3)
  
              # with NaT
              s = df['dt'].copy()
              s = klass([v for v in s.values] + [pd.NaT])
  
              result = s.value_counts()
              self.assertEqual(result.index.dtype, 'datetime64[ns]')
              tm.assert_series_equal(result, expected_s)
  
              result = s.value_counts(dropna=False)
              expected_s[pd.NaT] = 1
              tm.assert_series_equal(result, expected_s)
  
              unique = s.unique()
              self.assertEqual(unique.dtype, 'datetime64[ns]')
  
              # numpy_array_equal cannot compare pd.NaT
              if isinstance(s, Index):
                  exp_idx = DatetimeIndex(expected.tolist() + [pd.NaT])
                  tm.assert_index_equal(unique, exp_idx)
              else:
                  tm.assert_numpy_array_equal(unique[:3], expected)
                  self.assertTrue(pd.isnull(unique[3]))
  
              self.assertEqual(s.nunique(), 3)
              self.assertEqual(s.nunique(dropna=False), 4)
  
              # timedelta64[ns]
              td = df.dt - df.dt + timedelta(1)
              td = klass(td, name='dt')
  
              result = td.value_counts()
              expected_s = Series([6], index=[Timedelta('1day')], name='dt')
              tm.assert_series_equal(result, expected_s)
  
              expected = TimedeltaIndex(['1 days'], name='dt')
              if isinstance(td, Index):
                  tm.assert_index_equal(td.unique(), expected)
              else:
                  tm.assert_numpy_array_equal(td.unique(), expected.values)
  
              td2 = timedelta(1) + (df.dt - df.dt)
              td2 = klass(td2, name='dt')
              result2 = td2.value_counts()
              tm.assert_series_equal(result2, expected_s)
  
      def test_factorize(self):
          for orig in self.objs:
              o = orig.copy()
  
              if isinstance(o, Index) and o.is_boolean():
                  exp_arr = np.array([0, 1] + [0] * 8, dtype=np.intp)
                  exp_uniques = o
                  exp_uniques = Index([False, True])
              else:
                  exp_arr = np.array(range(len(o)), dtype=np.intp)
                  exp_uniques = o
              labels, uniques = o.factorize()
  
              self.assert_numpy_array_equal(labels, exp_arr)
              if isinstance(o, Series):
                  self.assert_index_equal(uniques, Index(orig),
                                          check_names=False)
              else:
                  # factorize explicitly resets name
                  self.assert_index_equal(uniques, exp_uniques,
                                          check_names=False)
  
      def test_factorize_repeated(self):
          for orig in self.objs:
              o = orig.copy()
  
              # don't test boolean
              if isinstance(o, Index) and o.is_boolean():
                  continue
  
              # sort by value, and create duplicates
              if isinstance(o, Series):
                  o = o.sort_values()
                  n = o.iloc[5:].append(o)
              else:
                  indexer = o.argsort()
                  o = o.take(indexer)
                  n = o[5:].append(o)
  
              exp_arr = np.array([5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
                                 dtype=np.intp)
              labels, uniques = n.factorize(sort=True)
  
              self.assert_numpy_array_equal(labels, exp_arr)
              if isinstance(o, Series):
                  self.assert_index_equal(uniques, Index(orig).sort_values(),
                                          check_names=False)
              else:
                  self.assert_index_equal(uniques, o, check_names=False)
  
              exp_arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4],
                                 np.intp)
              labels, uniques = n.factorize(sort=False)
              self.assert_numpy_array_equal(labels, exp_arr)
  
              if isinstance(o, Series):
                  expected = Index(o.iloc[5:10].append(o.iloc[:5]))
                  self.assert_index_equal(uniques, expected, check_names=False)
              else:
                  expected = o[5:10].append(o[:5])
                  self.assert_index_equal(uniques, expected, check_names=False)
  
      def test_duplicated_drop_duplicates_index(self):
          # GH 4060
          for original in self.objs:
              if isinstance(original, Index):
  
                  # special case
                  if original.is_boolean():
                      result = original.drop_duplicates()
                      expected = Index([False, True], name='a')
                      tm.assert_index_equal(result, expected)
                      continue
  
                  # original doesn't have duplicates
                  expected = np.array([False] * len(original), dtype=bool)
                  duplicated = original.duplicated()
                  tm.assert_numpy_array_equal(duplicated, expected)
                  self.assertTrue(duplicated.dtype == bool)
                  result = original.drop_duplicates()
                  tm.assert_index_equal(result, original)
                  self.assertFalse(result is original)
  
                  # has_duplicates
                  self.assertFalse(original.has_duplicates)
  
                  # create repeated values, 3rd and 5th values are duplicated
                  idx = original[list(range(len(original))) + [5, 3]]
                  expected = np.array([False] * len(original) + [True, True],
                                      dtype=bool)
                  duplicated = idx.duplicated()
                  tm.assert_numpy_array_equal(duplicated, expected)
                  self.assertTrue(duplicated.dtype == bool)
                  tm.assert_index_equal(idx.drop_duplicates(), original)
  
                  base = [False] * len(idx)
                  base[3] = True
                  base[5] = True
                  expected = np.array(base)
  
                  duplicated = idx.duplicated(keep='last')
                  tm.assert_numpy_array_equal(duplicated, expected)
                  self.assertTrue(duplicated.dtype == bool)
                  result = idx.drop_duplicates(keep='last')
                  tm.assert_index_equal(result, idx[~expected])
  
                  # deprecate take_last
                  with tm.assert_produces_warning(FutureWarning):
                      duplicated = idx.duplicated(take_last=True)
                  tm.assert_numpy_array_equal(duplicated, expected)
                  self.assertTrue(duplicated.dtype == bool)
                  with tm.assert_produces_warning(FutureWarning):
                      result = idx.drop_duplicates(take_last=True)
                  tm.assert_index_equal(result, idx[~expected])
  
                  base = [False] * len(original) + [True, True]
                  base[3] = True
                  base[5] = True
                  expected = np.array(base)
  
                  duplicated = idx.duplicated(keep=False)
                  tm.assert_numpy_array_equal(duplicated, expected)
                  self.assertTrue(duplicated.dtype == bool)
                  result = idx.drop_duplicates(keep=False)
                  tm.assert_index_equal(result, idx[~expected])
  
                  with tm.assertRaisesRegexp(
                          TypeError, r"drop_duplicates\(\) got an unexpected "
                          "keyword argument"):
                      idx.drop_duplicates(inplace=True)
  
              else:
                  expected = Series([False] * len(original),
                                    index=original.index, name='a')
                  tm.assert_series_equal(original.duplicated(), expected)
                  result = original.drop_duplicates()
                  tm.assert_series_equal(result, original)
                  self.assertFalse(result is original)
  
                  idx = original.index[list(range(len(original))) + [5, 3]]
                  values = original._values[list(range(len(original))) + [5, 3]]
                  s = Series(values, index=idx, name='a')
  
                  expected = Series([False] * len(original) + [True, True],
                                    index=idx, name='a')
                  tm.assert_series_equal(s.duplicated(), expected)
                  tm.assert_series_equal(s.drop_duplicates(), original)
  
                  base = [False] * len(idx)
                  base[3] = True
                  base[5] = True
                  expected = Series(base, index=idx, name='a')
  
                  tm.assert_series_equal(s.duplicated(keep='last'), expected)
                  tm.assert_series_equal(s.drop_duplicates(keep='last'),
                                         s[~np.array(base)])
  
                  # deprecate take_last
                  with tm.assert_produces_warning(FutureWarning):
                      tm.assert_series_equal(
                          s.duplicated(take_last=True), expected)
                  with tm.assert_produces_warning(FutureWarning):
                      tm.assert_series_equal(s.drop_duplicates(take_last=True),
                                             s[~np.array(base)])
                  base = [False] * len(original) + [True, True]
                  base[3] = True
                  base[5] = True
                  expected = Series(base, index=idx, name='a')
  
                  tm.assert_series_equal(s.duplicated(keep=False), expected)
                  tm.assert_series_equal(s.drop_duplicates(keep=False),
                                         s[~np.array(base)])
  
                  s.drop_duplicates(inplace=True)
                  tm.assert_series_equal(s, original)
  
      def test_drop_duplicates_series_vs_dataframe(self):
          # GH 14192
          df = pd.DataFrame({'a': [1, 1, 1, 'one', 'one'],
                             'b': [2, 2, np.nan, np.nan, np.nan],
                             'c': [3, 3, np.nan, np.nan, 'three'],
                             'd': [1, 2, 3, 4, 4],
                             'e': [datetime(2015, 1, 1), datetime(2015, 1, 1),
                                   datetime(2015, 2, 1), pd.NaT, pd.NaT]
                             })
          for column in df.columns:
              for keep in ['first', 'last', False]:
                  dropped_frame = df[[column]].drop_duplicates(keep=keep)
                  dropped_series = df[column].drop_duplicates(keep=keep)
                  tm.assert_frame_equal(dropped_frame, dropped_series.to_frame())
  
      def test_fillna(self):
          # # GH 11343
          # though Index.fillna and Series.fillna has separate impl,
          # test here to confirm these works as the same
  
          for orig in self.objs:
  
              o = orig.copy()
              values = o.values
  
              # values will not be changed
              result = o.fillna(o.astype(object).values[0])
              if isinstance(o, Index):
                  self.assert_index_equal(o, result)
              else:
                  self.assert_series_equal(o, result)
              # check shallow_copied
              self.assertFalse(o is result)
  
          for null_obj in [np.nan, None]:
              for orig in self.objs:
                  o = orig.copy()
                  klass = type(o)
  
                  if not self._allow_na_ops(o):
                      continue
  
                  if needs_i8_conversion(o):
  
                      values = o.astype(object).values
                      fill_value = values[0]
                      values[0:2] = pd.NaT
                  else:
                      values = o.values.copy()
                      fill_value = o.values[0]
                      values[0:2] = null_obj
  
                  expected = [fill_value] * 2 + list(values[2:])
  
                  expected = klass(expected)
                  o = klass(values)
  
                  # check values has the same dtype as the original
                  self.assertEqual(o.dtype, orig.dtype)
  
                  result = o.fillna(fill_value)
                  if isinstance(o, Index):
                      self.assert_index_equal(result, expected)
                  else:
                      self.assert_series_equal(result, expected)
                  # check shallow_copied
                  self.assertFalse(o is result)
  
      def test_memory_usage(self):
          for o in self.objs:
              res = o.memory_usage()
              res_deep = o.memory_usage(deep=True)
  
              if (is_object_dtype(o) or (isinstance(o, Series) and
                                         is_object_dtype(o.index))):
                  # if there are objects, only deep will pick them up
                  self.assertTrue(res_deep > res)
              else:
                  self.assertEqual(res, res_deep)
  
              if isinstance(o, Series):
                  self.assertEqual(
                      (o.memory_usage(index=False) +
                          o.index.memory_usage()),
                      o.memory_usage(index=True)
                  )
  
              # sys.getsizeof will call the .memory_usage with
              # deep=True, and add on some GC overhead
              diff = res_deep - sys.getsizeof(o)
              self.assertTrue(abs(diff) < 100)
  
      def test_searchsorted(self):
          # See gh-12238
          for o in self.objs:
              index = np.searchsorted(o, max(o))
              self.assertTrue(0 <= index <= len(o))
  
              index = np.searchsorted(o, max(o), sorter=range(len(o)))
              self.assertTrue(0 <= index <= len(o))
  
      def test_validate_bool_args(self):
          invalid_values = [1, "True", [1, 2, 3], 5.0]
  
          for value in invalid_values:
              with self.assertRaises(ValueError):
                  self.int_series.drop_duplicates(inplace=value)
  
  
  class TestTranspose(Ops):
      errmsg = "the 'axes' parameter is not supported"
  
      def test_transpose(self):
          for obj in self.objs:
              if isinstance(obj, Index):
                  tm.assert_index_equal(obj.transpose(), obj)
              else:
                  tm.assert_series_equal(obj.transpose(), obj)
  
      def test_transpose_non_default_axes(self):
          for obj in self.objs:
              tm.assertRaisesRegexp(ValueError, self.errmsg,
                                    obj.transpose, 1)
              tm.assertRaisesRegexp(ValueError, self.errmsg,
                                    obj.transpose, axes=1)
  
      def test_numpy_transpose(self):
          for obj in self.objs:
              if isinstance(obj, Index):
                  tm.assert_index_equal(np.transpose(obj), obj)
              else:
                  tm.assert_series_equal(np.transpose(obj), obj)
  
              tm.assertRaisesRegexp(ValueError, self.errmsg,
                                    np.transpose, obj, axes=1)
  
  
  class TestNoNewAttributesMixin(tm.TestCase):
  
      def test_mixin(self):
          class T(NoNewAttributesMixin):
              pass
  
          t = T()
          self.assertFalse(hasattr(t, "__frozen"))
          t.a = "test"
          self.assertEqual(t.a, "test")
          t._freeze()
          # self.assertTrue("__frozen" not in dir(t))
          self.assertIs(getattr(t, "__frozen"), True)
  
          def f():
              t.b = "test"
  
          self.assertRaises(AttributeError, f)
          self.assertFalse(hasattr(t, "b"))
  
  
  if __name__ == '__main__':
      import nose
  
      nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'],
                     # '--with-coverage', '--cover-package=pandas.core'],
                     exit=False)
   # coding: utf-8
  
  import nose
  import itertools
  import string
  from distutils.version import LooseVersion
  
  from pandas import Series, DataFrame, MultiIndex
  from pandas.compat import range, lzip
  import pandas.util.testing as tm
  from pandas.util.testing import slow
  
  import numpy as np
  from numpy import random
  from numpy.random import randn
  
  import pandas.tools.plotting as plotting
  
  from pandas.tests.plotting.common import (TestPlotBase, _check_plot_works)
  
  
  """ Test cases for .boxplot method """
  
  
  def _skip_if_mpl_14_or_dev_boxplot():
      # GH 8382
      # Boxplot failures on 1.4 and 1.4.1
      # Don't need try / except since that's done at class level
      import matplotlib
      if str(matplotlib.__version__) >= LooseVersion('1.4'):
          raise nose.SkipTest("Matplotlib Regression in 1.4 and current dev.")
  
  
  @tm.mplskip
  class TestDataFramePlots(TestPlotBase):
  
      @slow
      def test_boxplot_legacy(self):
          df = DataFrame(randn(6, 4),
                         index=list(string.ascii_letters[:6]),
                         columns=['one', 'two', 'three', 'four'])
          df['indic'] = ['foo', 'bar'] * 3
          df['indic2'] = ['foo', 'bar', 'foo'] * 2
  
          _check_plot_works(df.boxplot, return_type='dict')
          _check_plot_works(df.boxplot, column=[
                            'one', 'two'], return_type='dict')
          # _check_plot_works adds an ax so catch warning. see GH #13188
          with tm.assert_produces_warning(UserWarning):
              _check_plot_works(df.boxplot, column=['one', 'two'],
                                by='indic')
          _check_plot_works(df.boxplot, column='one', by=['indic', 'indic2'])
          with tm.assert_produces_warning(UserWarning):
              _check_plot_works(df.boxplot, by='indic')
          with tm.assert_produces_warning(UserWarning):
              _check_plot_works(df.boxplot, by=['indic', 'indic2'])
          _check_plot_works(plotting.boxplot, data=df['one'], return_type='dict')
          _check_plot_works(df.boxplot, notch=1, return_type='dict')
          with tm.assert_produces_warning(UserWarning):
              _check_plot_works(df.boxplot, by='indic', notch=1)
  
          df = DataFrame(np.random.rand(10, 2), columns=['Col1', 'Col2'])
          df['X'] = Series(['A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B'])
          df['Y'] = Series(['A'] * 10)
          with tm.assert_produces_warning(UserWarning):
              _check_plot_works(df.boxplot, by='X')
  
          # When ax is supplied and required number of axes is 1,
          # passed ax should be used:
          fig, ax = self.plt.subplots()
          axes = df.boxplot('Col1', by='X', ax=ax)
          ax_axes = ax.axes if self.mpl_ge_1_5_0 else ax.get_axes()
          self.assertIs(ax_axes, axes)
  
          fig, ax = self.plt.subplots()
          axes = df.groupby('Y').boxplot(ax=ax, return_type='axes')
          ax_axes = ax.axes if self.mpl_ge_1_5_0 else ax.get_axes()
          self.assertIs(ax_axes, axes['A'])
  
          # Multiple columns with an ax argument should use same figure
          fig, ax = self.plt.subplots()
          with tm.assert_produces_warning(UserWarning):
              axes = df.boxplot(column=['Col1', 'Col2'],
                                by='X', ax=ax, return_type='axes')
          self.assertIs(axes['Col1'].get_figure(), fig)
  
          # When by is None, check that all relevant lines are present in the
          # dict
          fig, ax = self.plt.subplots()
          d = df.boxplot(ax=ax, return_type='dict')
          lines = list(itertools.chain.from_iterable(d.values()))
          self.assertEqual(len(ax.get_lines()), len(lines))
  
      @slow
      def test_boxplot_return_type_none(self):
          # GH 12216; return_type=None & by=None -> axes
          result = self.hist_df.boxplot()
          self.assertTrue(isinstance(result, self.plt.Axes))
  
      @slow
      def test_boxplot_return_type_legacy(self):
          # API change in https://github.com/pandas-dev/pandas/pull/7096
          import matplotlib as mpl  # noqa
  
          df = DataFrame(randn(6, 4),
                         index=list(string.ascii_letters[:6]),
                         columns=['one', 'two', 'three', 'four'])
          with tm.assertRaises(ValueError):
              df.boxplot(return_type='NOTATYPE')
  
          result = df.boxplot()
          self._check_box_return_type(result, 'axes')
  
          with tm.assert_produces_warning(False):
              result = df.boxplot(return_type='dict')
          self._check_box_return_type(result, 'dict')
  
          with tm.assert_produces_warning(False):
              result = df.boxplot(return_type='axes')
          self._check_box_return_type(result, 'axes')
  
          with tm.assert_produces_warning(False):
              result = df.boxplot(return_type='both')
          self._check_box_return_type(result, 'both')
  
      @slow
      def test_boxplot_axis_limits(self):
  
          def _check_ax_limits(col, ax):
              y_min, y_max = ax.get_ylim()
              self.assertTrue(y_min <= col.min())
              self.assertTrue(y_max >= col.max())
  
          df = self.hist_df.copy()
          df['age'] = np.random.randint(1, 20, df.shape[0])
          # One full row
          height_ax, weight_ax = df.boxplot(['height', 'weight'], by='category')
          _check_ax_limits(df['height'], height_ax)
          _check_ax_limits(df['weight'], weight_ax)
          self.assertEqual(weight_ax._sharey, height_ax)
  
          # Two rows, one partial
          p = df.boxplot(['height', 'weight', 'age'], by='category')
          height_ax, weight_ax, age_ax = p[0, 0], p[0, 1], p[1, 0]
          dummy_ax = p[1, 1]
  
          _check_ax_limits(df['height'], height_ax)
          _check_ax_limits(df['weight'], weight_ax)
          _check_ax_limits(df['age'], age_ax)
          self.assertEqual(weight_ax._sharey, height_ax)
          self.assertEqual(age_ax._sharey, height_ax)
          self.assertIsNone(dummy_ax._sharey)
  
      @slow
      def test_boxplot_empty_column(self):
          _skip_if_mpl_14_or_dev_boxplot()
          df = DataFrame(np.random.randn(20, 4))
          df.loc[:, 0] = np.nan
          _check_plot_works(df.boxplot, return_type='axes')
  
  
  @tm.mplskip
  class TestDataFrameGroupByPlots(TestPlotBase):
  
      @slow
      def test_boxplot_legacy(self):
          grouped = self.hist_df.groupby(by='gender')
          with tm.assert_produces_warning(UserWarning):
              axes = _check_plot_works(grouped.boxplot, return_type='axes')
          self._check_axes_shape(list(axes.values), axes_num=2, layout=(1, 2))
          axes = _check_plot_works(grouped.boxplot, subplots=False,
                                   return_type='axes')
          self._check_axes_shape(axes, axes_num=1, layout=(1, 1))
          tuples = lzip(string.ascii_letters[:10], range(10))
          df = DataFrame(np.random.rand(10, 3),
                         index=MultiIndex.from_tuples(tuples))
  
          grouped = df.groupby(level=1)
          with tm.assert_produces_warning(UserWarning):
              axes = _check_plot_works(grouped.boxplot, return_type='axes')
          self._check_axes_shape(list(axes.values), axes_num=10, layout=(4, 3))
  
          axes = _check_plot_works(grouped.boxplot, subplots=False,
                                   return_type='axes')
          self._check_axes_shape(axes, axes_num=1, layout=(1, 1))
  
          grouped = df.unstack(level=1).groupby(level=0, axis=1)
          with tm.assert_produces_warning(UserWarning):
              axes = _check_plot_works(grouped.boxplot, return_type='axes')
          self._check_axes_shape(list(axes.values), axes_num=3, layout=(2, 2))
          axes = _check_plot_works(grouped.boxplot, subplots=False,
                                   return_type='axes')
          self._check_axes_shape(axes, axes_num=1, layout=(1, 1))
  
      @slow
      def test_grouped_plot_fignums(self):
          n = 10
          weight = Series(np.random.normal(166, 20, size=n))
          height = Series(np.random.normal(60, 10, size=n))
          with tm.RNGContext(42):
              gender = np.random.choice(['male', 'female'], size=n)
          df = DataFrame({'height': height, 'weight': weight, 'gender': gender})
          gb = df.groupby('gender')
  
          res = gb.plot()
          self.assertEqual(len(self.plt.get_fignums()), 2)
          self.assertEqual(len(res), 2)
          tm.close()
  
          res = gb.boxplot(return_type='axes')
          self.assertEqual(len(self.plt.get_fignums()), 1)
          self.assertEqual(len(res), 2)
          tm.close()
  
          # now works with GH 5610 as gender is excluded
          res = df.groupby('gender').hist()
          tm.close()
  
      @slow
      def test_grouped_box_return_type(self):
          df = self.hist_df
  
          # old style: return_type=None
          result = df.boxplot(by='gender')
          self.assertIsInstance(result, np.ndarray)
          self._check_box_return_type(
              result, None,
              expected_keys=['height', 'weight', 'category'])
  
          # now for groupby
          result = df.groupby('gender').boxplot(return_type='dict')
          self._check_box_return_type(
              result, 'dict', expected_keys=['Male', 'Female'])
  
          columns2 = 'X B C D A G Y N Q O'.split()
          df2 = DataFrame(random.randn(50, 10), columns=columns2)
          categories2 = 'A B C D E F G H I J'.split()
          df2['category'] = categories2 * 5
  
          for t in ['dict', 'axes', 'both']:
              returned = df.groupby('classroom').boxplot(return_type=t)
              self._check_box_return_type(
                  returned, t, expected_keys=['A', 'B', 'C'])
  
              returned = df.boxplot(by='classroom', return_type=t)
              self._check_box_return_type(
                  returned, t,
                  expected_keys=['height', 'weight', 'category'])
  
              returned = df2.groupby('category').boxplot(return_type=t)
              self._check_box_return_type(returned, t, expected_keys=categories2)
  
              returned = df2.boxplot(by='category', return_type=t)
              self._check_box_return_type(returned, t, expected_keys=columns2)
  
      @slow
      def test_grouped_box_layout(self):
          df = self.hist_df
  
          self.assertRaises(ValueError, df.boxplot, column=['weight', 'height'],
                            by=df.gender, layout=(1, 1))
          self.assertRaises(ValueError, df.boxplot,
                            column=['height', 'weight', 'category'],
                            layout=(2, 1), return_type='dict')
          self.assertRaises(ValueError, df.boxplot, column=['weight', 'height'],
                            by=df.gender, layout=(-1, -1))
  
          # _check_plot_works adds an ax so catch warning. see GH #13188
          with tm.assert_produces_warning(UserWarning):
              box = _check_plot_works(df.groupby('gender').boxplot,
                                      column='height', return_type='dict')
          self._check_axes_shape(self.plt.gcf().axes, axes_num=2, layout=(1, 2))
  
          with tm.assert_produces_warning(UserWarning):
              box = _check_plot_works(df.groupby('category').boxplot,
                                      column='height',
                                      return_type='dict')
          self._check_axes_shape(self.plt.gcf().axes, axes_num=4, layout=(2, 2))
  
          # GH 6769
          with tm.assert_produces_warning(UserWarning):
              box = _check_plot_works(df.groupby('classroom').boxplot,
                                      column='height', return_type='dict')
          self._check_axes_shape(self.plt.gcf().axes, axes_num=3, layout=(2, 2))
  
          # GH 5897
          axes = df.boxplot(column=['height', 'weight', 'category'], by='gender',
                            return_type='axes')
          self._check_axes_shape(self.plt.gcf().axes, axes_num=3, layout=(2, 2))
          for ax in [axes['height']]:
              self._check_visible(ax.get_xticklabels(), visible=False)
              self._check_visible([ax.xaxis.get_label()], visible=False)
          for ax in [axes['weight'], axes['category']]:
              self._check_visible(ax.get_xticklabels())
              self._check_visible([ax.xaxis.get_label()])
  
          box = df.groupby('classroom').boxplot(
              column=['height', 'weight', 'category'], return_type='dict')
          self._check_axes_shape(self.plt.gcf().axes, axes_num=3, layout=(2, 2))
  
          with tm.assert_produces_warning(UserWarning):
              box = _check_plot_works(df.groupby('category').boxplot,
                                      column='height',
                                      layout=(3, 2), return_type='dict')
          self._check_axes_shape(self.plt.gcf().axes, axes_num=4, layout=(3, 2))
          with tm.assert_produces_warning(UserWarning):
              box = _check_plot_works(df.groupby('category').boxplot,
                                      column='height',
                                      layout=(3, -1), return_type='dict')
          self._check_axes_shape(self.plt.gcf().axes, axes_num=4, layout=(3, 2))
  
          box = df.boxplot(column=['height', 'weight', 'category'], by='gender',
                           layout=(4, 1))
          self._check_axes_shape(self.plt.gcf().axes, axes_num=3, layout=(4, 1))
  
          box = df.boxplot(column=['height', 'weight', 'category'], by='gender',
                           layout=(-1, 1))
          self._check_axes_shape(self.plt.gcf().axes, axes_num=3, layout=(3, 1))
  
          box = df.groupby('classroom').boxplot(
              column=['height', 'weight', 'category'], layout=(1, 4),
              return_type='dict')
          self._check_axes_shape(self.plt.gcf().axes, axes_num=3, layout=(1, 4))
  
          box = df.groupby('classroom').boxplot(  # noqa
              column=['height', 'weight', 'category'], layout=(1, -1),
              return_type='dict')
          self._check_axes_shape(self.plt.gcf().axes, axes_num=3, layout=(1, 3))
  
      @slow
      def test_grouped_box_multiple_axes(self):
          # GH 6970, GH 7069
          df = self.hist_df
  
          # check warning to ignore sharex / sharey
          # this check should be done in the first function which
          # passes multiple axes to plot, hist or boxplot
          # location should be changed if other test is added
          # which has earlier alphabetical order
          with tm.assert_produces_warning(UserWarning):
              fig, axes = self.plt.subplots(2, 2)
              df.groupby('category').boxplot(
                  column='height', return_type='axes', ax=axes)
              self._check_axes_shape(self.plt.gcf().axes,
                                     axes_num=4, layout=(2, 2))
  
          fig, axes = self.plt.subplots(2, 3)
          with tm.assert_produces_warning(UserWarning):
              returned = df.boxplot(column=['height', 'weight', 'category'],
                                    by='gender', return_type='axes', ax=axes[0])
          returned = np.array(list(returned.values))
          self._check_axes_shape(returned, axes_num=3, layout=(1, 3))
          self.assert_numpy_array_equal(returned, axes[0])
          self.assertIs(returned[0].figure, fig)
  
          # draw on second row
          with tm.assert_produces_warning(UserWarning):
              returned = df.groupby('classroom').boxplot(
                  column=['height', 'weight', 'category'],
                  return_type='axes', ax=axes[1])
          returned = np.array(list(returned.values))
          self._check_axes_shape(returned, axes_num=3, layout=(1, 3))
          self.assert_numpy_array_equal(returned, axes[1])
          self.assertIs(returned[0].figure, fig)
  
          with tm.assertRaises(ValueError):
              fig, axes = self.plt.subplots(2, 3)
              # pass different number of axes from required
              with tm.assert_produces_warning(UserWarning):
                  axes = df.groupby('classroom').boxplot(ax=axes)
  
  
  if __name__ == '__main__':
      nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'],
                     exit=False)
  
apis: pandas.Series pandas.util.testing.makeFloatIndex pandas.core.base.FrozenNDArray pandas.types.common.is_datetimetz pandas.util.testing.assert_produces_warning pandas.util.testing.assert_series_equal pandas.util.testing.makeStringIndex pandas.util.testing.makeIntIndex numpy.transpose pandas.compat.StringIO pandas.to_datetime pandas.isnull numpy.unique pandas.util.testing.makeDateIndex pandas.util.testing.makeUnicodeIndex pandas.util.testing.assert_numpy_array_equal pandas.types.common.needs_i8_conversion pandas.read_fwf pandas.TimedeltaIndex numpy.arange pandas.Timedelta pandas.util.testing.assertRaisesRegexp pandas.util.testing.assert_index_equal pandas.Index numpy.array pandas.compat.u pandas.DatetimeIndex numpy.random.randn pandas.compat.numpy.np_array_datetime64_compat pandas.types.common.is_object_dtype pandas.util.testing.makePeriodIndex pandas.core.base.FrozenList pandas.util.testing.makeBoolIndex
apis: pandas.util.testing.RNGContext pandas.Series pandas.DataFrame numpy.random.randn numpy.random.normal numpy.random.choice pandas.util.testing.assert_produces_warning pandas.util.testing.close numpy.random.rand pandas.compat.range pandas.MultiIndex.from_tuples pandas.tests.plotting.common._check_plot_works numpy.random.randint pandas.util.testing.assertRaises