Source code for yellowbrick.utils

# yellowbrick.utils
# Utility functions and helpers for the Yellowbrick library.
#
# Author:   Jason Keung <jason.s.keung@gmail.com>
# Author:   Patrick O'Melveny <pvomelveny@gmail.com>
# Author:   Benjamin Bengfort <bbengfort@districtdatalabs.com>
# Author:   Rebecca Bilbro <rbilbro@districtdatalabs.com>
# Created:  Thu Jun 02 15:33:18 2016 -0500
#
# Copyright (C) 2016 District Data LAbs
# For license information, see LICENSE.txt
#
# ID: utils.py [] jason.s.keung@gmail.com $

"""
Utility functions and helpers for the Yellowbrick library.
"""

##########################################################################
## Imports
##########################################################################

import inspect

from functools import wraps
from sklearn.pipeline import Pipeline
from sklearn.base import BaseEstimator

from yellowbrick.exceptions import YellowbrickTypeError


##########################################################################
## Model detection utilities
##########################################################################

[docs]def get_model_name(model): """ Detects the model name for a Scikit-Learn model or pipeline Parameters ---------- model: class or instance The object to determine the name for """ if not is_estimator(model): raise YellowbrickTypeError( "Cannot detect the model name for non estimator: '{}'".format( type(model) ) ) else: if isinstance(model, Pipeline): return model.steps[-1][-1].__class__.__name__ else: return model.__class__.__name__
########################################################################## ## Type checking utilities ##########################################################################
[docs]def is_estimator(model): """ Determines if a model is an estimator using issubclass and isinstance. Parameters ---------- model: class or instance The object to test whether or not is a Scikit-Learn estimator. """ if inspect.isclass(model): return issubclass(model, BaseEstimator) return isinstance(model, BaseEstimator)
# Alias for closer name to isinstance and issubclass isestimator = is_estimator
[docs]def is_classifier(estimator): """ Returns True if the given estimator is (probably) a classifier. Parameters ---------- estimator: class or instance The object to test whether or not is a Scikit-Learn classifier. See also -------- is_classifier `sklearn.is_classifier() <https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/base.py#L518>`_ """ # TODO: once we make ScoreVisualizer and ModelVisualizer pass through # wrappers as in Issue #90, these three lines become unnecessary. # NOTE: This must be imported here to avoid recursive import. from yellowbrick.base import Visualizer if isinstance(estimator, Visualizer): return is_classifier(estimator.estimator) # Test the _estimator_type property return getattr(estimator, "_estimator_type", None) == "classifier"
# Alias for closer name to isinstance and issubclass isclassifier = is_classifier
[docs]def is_regressor(estimator): """ Returns True if the given estimator is (probably) a regressor. Parameters ---------- model: class or instance The object to test whether or not is a Scikit-Learn regressor. See also -------- is_regressor `sklearn.is_regressor() <https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/base.py#L531>`_ """ # TODO: once we make ScoreVisualizer and ModelVisualizer pass through # wrappers as in Issue #90, these three lines become unnecessary. # NOTE: This must be imported here to avoid recursive import. from yellowbrick.base import Visualizer if isinstance(estimator, Visualizer): return is_regressor(estimator.estimator) # Test the _estimator_type property return getattr(estimator, "_estimator_type", None) == "regressor"
# Alias for closer name to isinstance and issubclass isregressor = is_regressor
[docs]def is_dataframe(obj): """ Returns True if the given object is a Pandas Data Frame. Parameters ---------- obj: instance The object to test whether or not is a Pandas DataFrame. """ try: # This is the best method of type checking from pandas import DataFrame return isinstance(obj, DataFrame) except ImportError: # Pandas is not a dependency, so this is scary return obj.__class__.__name__ == "DataFrame"
# Alias for closer name to isinstance and issubclass isdataframe = is_dataframe ########################################################################## ## Decorators ##########################################################################
[docs]def memoized(fget): """ Return a property attribute for new-style classes that only calls its getter on the first access. The result is stored and on subsequent accesses is returned, preventing the need to call the getter any more. Parameters ---------- fget: function The getter method to memoize for subsequent access. See also -------- python-memoized-property `python-memoized-property <https://github.com/estebistec/python-memoized-property>`_ """ attr_name = '_{0}'.format(fget.__name__) @wraps(fget) def fget_memoized(self): if not hasattr(self, attr_name): setattr(self, attr_name, fget(self)) return getattr(self, attr_name) return property(fget_memoized)
[docs]class docutil(object): """ This decorator can be used to apply the doc string from another function to the decorated function. This is used for our single call wrapper functions who implement the visualizer API without forcing the user to jump through all the hoops. The docstring of both the visualizer and the single call wrapper should be identical, this decorator ensures that we only have to edit one doc string. Usage:: @docutil(Visualizer.__init__) def visualize(*args, **kwargs): pass The basic usage is that you instantiate the decorator with the function whose docstring you want to copy, then apply that decorator to the the function whose docstring you would like modified. Note that this decorator performs no wrapping of the target function. """ def __init__(self, func): """Create a decorator to document other functions with the specified function's doc string. Parameters ---------- func : function The function whose doc string we should decorate with """ self.doc = func.__doc__ def __call__(self, func): """Modify the decorated function with the stored doc string. Parameters ---------- func: function The function to apply the saved doc string to. """ func.__doc__ = self.doc return func