# Path: skutil/base.py
# def overrides(interface_class):
#     """Decorator for methods that override super methods. Provides
#     runtime validation that the method is, in fact, inherited from the
#     superclass. If not, will raise an ``AssertionError``.
# 
#     Parameters
#     ----------
# 
#     interface_class : type
#         The class/type from which the specified method is inherited.
#         If the method does not exist in the specified type, a ``RuntimeError``
#         will be raised.
# 
# 
#     Examples
#     --------
#     
#     The following is valid use:
# 
#         >>> class A(object):
#         ...     def a(self):
#         ...         return 1
# 
#         >>> class B(A):
#         ...     @overrides(A)
#         ...     def a(self):
#         ...         return 2
#         ...
#         ...     def b(self):
#         ...         return 0
# 
#     The following would be an invalid ``overrides`` statement, since
#     ``A`` does not have a ``b`` method to override.
# 
#         >>> class C(B): # doctest: +IGNORE_EXCEPTION_DETAIL
#         ...     @overrides(A) # should override B, not A
#         ...     def b(self):
#         ...         return 1
#         Traceback (most recent call last):  
#         AssertionError: A.b must override a super method!
# 
# 
#     .. versionadded:: 0.1.0
#     """
# 
#     def overrider(method):
#         assert (method.__name__ in dir(interface_class)), '%s.%s must override a super method!' % (
#             interface_class.__name__, method.__name__)
#         return method
# 
#     return overrider
# 
# class BaseSkutil(six.with_metaclass(ABCMeta, BaseEstimator, SelectiveMixin)):
#     """Provides the base class for all non-h2o skutil transformers.
#     Implements ``SelectiveMixin``. Also provides the "pretty-print" 
#     ``__repr__`` implemented in sklearn's ``BaseEstimator``.
# 
#     Parameters
#     ----------
# 
#     cols : array_like, shape=(n_features,), optional (default=None)
#         The names of the columns on which to apply the transformation.
#         If no column names are provided, the transformer will be ``fit``
#         on the entire frame. Note that the transformation will also only
#         apply to the specified columns, and any other non-specified
#         columns will still be present after transformation.
# 
#     as_df : bool, optional (default=True)
#         Whether to return a Pandas ``DataFrame`` in the ``transform``
#         method. If False, will return a Numpy ``ndarray`` instead. 
#         Since most skutil transformers depend on explicitly-named
#         ``DataFrame`` features, the ``as_df`` parameter is True by default.
# 
# 
#     Examples
#     --------
# 
#         >>> from skutil.base import BaseSkutil
#         >>> class A(BaseSkutil):
#         ...     def __init__(self, cols=None, as_df=None):
#         ...             super(A, self).__init__(cols, as_df)
#         ...
#         >>> A()
#         A(as_df=None, cols=None)
# 
#     """
#     
#     def __init__(self, cols=None, as_df=True):
#         self.cols = cols
#         self.as_df = as_df
# 
# Path: skutil/utils/fixes.py
# def dict_keys(d):
#     """In python 3, the ``d.keys()`` method
#     returns a view and not an actual list.
# 
#     Parameters
#     ----------
# 
#     d : dict
#         The dictionary
# 
# 
#     Returns
#     -------
# 
#     list
#     """
#     return list(d.keys())


import abc
import warnings
import numpy as np
import pandas as pd
from h2o.frame import H2OFrame
from numpy.random import choice
from sklearn.externals import six
from sklearn.neighbors import NearestNeighbors
from skutil.base import overrides, BaseSkutil
from ..utils.fixes import dict_keys
from ..utils import *
                warnings.warn('class %s only has one observation' % str(minority), SamplingWarning)

            current_ratio = min_ct / cts[majority]
            if current_ratio >= ratio:
                continue  # if ratio is already met, continue

            n_samples = n_required - min_ct  # the difference in the current present and the number we need
            if n_samples <= 0:  # the np maximum can cause weirdness
                continue  # move onto next class

            minority_recs = all_indices[target_col == minority]
            idcs = choice(minority_recs, n_samples, replace=True)
            sample_indices.extend(list(idcs))

        # make list
        all_indices = list(all_indices)
        all_indices.extend(sample_indices)

        # sorted because h2o doesn't play nicely with random indexing
        out = sorted(all_indices) if not shuffle else [j for j in np.random.permutation(all_indices)]
        return out


class _UndersamplingBalancePartitioner(_BaseBalancePartitioner):
    """Balance partitioner for undersampling the minority class"""

    def __init__(self, X, y_name, ratio, validation_function=_validate_x_y_ratio):
        super(_UndersamplingBalancePartitioner, self).__init__(
            X, y_name, ratio, validation_function)


# Path: skutil/base.py
# def overrides(interface_class):
#     """Decorator for methods that override super methods. Provides
#     runtime validation that the method is, in fact, inherited from the
#     superclass. If not, will raise an ``AssertionError``.
# 
#     Parameters
#     ----------
# 
#     interface_class : type
#         The class/type from which the specified method is inherited.
#         If the method does not exist in the specified type, a ``RuntimeError``
#         will be raised.
# 
# 
#     Examples
#     --------
#     
#     The following is valid use:
# 
#         >>> class A(object):
#         ...     def a(self):
#         ...         return 1
# 
#         >>> class B(A):
#         ...     @overrides(A)
#         ...     def a(self):
#         ...         return 2
#         ...
#         ...     def b(self):
#         ...         return 0
# 
#     The following would be an invalid ``overrides`` statement, since
#     ``A`` does not have a ``b`` method to override.
# 
#         >>> class C(B): # doctest: +IGNORE_EXCEPTION_DETAIL
#         ...     @overrides(A) # should override B, not A
#         ...     def b(self):
#         ...         return 1
#         Traceback (most recent call last):  
#         AssertionError: A.b must override a super method!
# 
# 
#     .. versionadded:: 0.1.0
#     """
# 
#     def overrider(method):
#         assert (method.__name__ in dir(interface_class)), '%s.%s must override a super method!' % (
#             interface_class.__name__, method.__name__)
#         return method
# 
#     return overrider
# 
# class BaseSkutil(six.with_metaclass(ABCMeta, BaseEstimator, SelectiveMixin)):
#     """Provides the base class for all non-h2o skutil transformers.
#     Implements ``SelectiveMixin``. Also provides the "pretty-print" 
#     ``__repr__`` implemented in sklearn's ``BaseEstimator``.
# 
#     Parameters
#     ----------
# 
#     cols : array_like, shape=(n_features,), optional (default=None)
#         The names of the columns on which to apply the transformation.
#         If no column names are provided, the transformer will be ``fit``
#         on the entire frame. Note that the transformation will also only
#         apply to the specified columns, and any other non-specified
#         columns will still be present after transformation.
# 
#     as_df : bool, optional (default=True)
#         Whether to return a Pandas ``DataFrame`` in the ``transform``
#         method. If False, will return a Numpy ``ndarray`` instead. 
#         Since most skutil transformers depend on explicitly-named
#         ``DataFrame`` features, the ``as_df`` parameter is True by default.
# 
# 
#     Examples
#     --------
# 
#         >>> from skutil.base import BaseSkutil
#         >>> class A(BaseSkutil):
#         ...     def __init__(self, cols=None, as_df=None):
#         ...             super(A, self).__init__(cols, as_df)
#         ...
#         >>> A()
#         A(as_df=None, cols=None)
# 
#     """
#     
#     def __init__(self, cols=None, as_df=True):
#         self.cols = cols
#         self.as_df = as_df
# 
# Path: skutil/utils/fixes.py
# def dict_keys(d):
#     """In python 3, the ``d.keys()`` method
#     returns a view and not an actual list.
# 
#     Parameters
#     ----------
# 
#     d : dict
#         The dictionary
# 
# 
#     Returns
#     -------
# 
#     list
#     """
#     return list(d.keys())


# Path: skutil/preprocessing/balance.py
import abc
import warnings
import numpy as np
import pandas as pd
from h2o.frame import H2OFrame
from numpy.random import choice
from sklearn.externals import six
from sklearn.neighbors import NearestNeighbors
from skutil.base import overrides, BaseSkutil
from ..utils.fixes import dict_keys
from ..utils import *

                warnings.warn('class %s only has one observation' % str(minority), SamplingWarning)

            current_ratio = min_ct / cts[majority]
            if current_ratio >= ratio:
                continue  # if ratio is already met, continue

            n_samples = n_required - min_ct  # the difference in the current present and the number we need
            if n_samples <= 0:  # the np maximum can cause weirdness
                continue  # move onto next class

            minority_recs = all_indices[target_col == minority]
            idcs = choice(minority_recs, n_samples, replace=True)
            sample_indices.extend(list(idcs))

        # make list
        all_indices = list(all_indices)
        all_indices.extend(sample_indices)

        # sorted because h2o doesn't play nicely with random indexing
        out = sorted(all_indices) if not shuffle else [j for j in np.random.permutation(all_indices)]
        return out


class _UndersamplingBalancePartitioner(_BaseBalancePartitioner):
    """Balance partitioner for undersampling the minority class"""

    def __init__(self, X, y_name, ratio, validation_function=_validate_x_y_ratio):
        super(_UndersamplingBalancePartitioner, self).__init__(
            X, y_name, ratio, validation_function)


    @overrides(_BaseBalancePartitioner)