ó
áp7]c           @   s¶   d  Z  d d l m Z d d l Z d d l m Z d d l m	 Z	 d d l
 m Z e j d d	 ƒ d
 e j d „ Z d e f d „  ƒ  YZ e ƒ  Z d e f d „  ƒ  YZ e ƒ  Z d S(   sò   
Support and standalone functions for Robust Linear Models

References
----------
PJ Huber.  'Robust Statistics' John Wiley and Sons, Inc., New York, 1981.

R Venables, B Ripley. 'Modern Applied Statistics in S'
    Springer, New York, 2002.
iÿÿÿÿ(   t   rangeN(   t   normi   (   t   norms(   t   toolsi   g      @i    c         C   sW   t  j |  ƒ }  t | ƒ r3 t  j | |  | ƒ } n  t  j t  j |  | ƒ | d | ƒS(   s¤  
    The Median Absolute Deviation along given axis of an array

    Parameters
    ----------
    a : array-like
        Input array.
    c : float, optional
        The normalization constant.  Defined as scipy.stats.norm.ppf(3/4.),
        which is approximately .6745.
    axis : int, optional
        The defaul is 0. Can also be None.
    center : callable or float
        If a callable is provided, such as the default `np.median` then it
        is expected to be called center(a). The axis argument will be applied
        via np.apply_over_axes. Otherwise, provide a float.

    Returns
    -------
    mad : float
        `mad` = median(abs(`a` - center))/`c`
    t   axis(   t   npt   asarrayt   callablet   apply_over_axest   mediant   fabs(   t   at   cR   t   center(    (    s7   lib/python2.7/site-packages/statsmodels/robust/scale.pyt   mad   s    t   Huberc           B   s>   e  Z d  Z d d d d d „ Z d d d d „ Z d „  Z RS(	   s.  
    Huber's proposal 2 for estimating location and scale jointly.

    Parameters
    ----------
    c : float, optional
        Threshold used in threshold for chi=psi**2.  Default value is 1.5.
    tol : float, optional
        Tolerance for convergence.  Default value is 1e-08.
    maxiter : int, optional0
        Maximum number of iterations.  Default value is 30.
    norm : statsmodels.robust.norms.RobustNorm, optional
        A robust norm used in M estimator of location. If None,
        the location estimator defaults to a one-step
        fixed point version of the M-estimator using Huber's T.

    call
        Return joint estimates of Huber's scale and location.

    Examples
    --------
    >>> import numpy as np
    >>> import statsmodels.api as sm
    >>> chem_data = np.array([2.20, 2.20, 2.4, 2.4, 2.5, 2.7, 2.8, 2.9, 3.03,
    ...        3.03, 3.10, 3.37, 3.4, 3.4, 3.4, 3.5, 3.6, 3.7, 3.7, 3.7, 3.7,
    ...        3.77, 5.28, 28.95])
    >>> sm.robust.scale.huber(chem_data)
    (array(3.2054980819923693), array(0.67365260010478967))
    g      ø?g:Œ0âŽyE>i   c         C   sm   | |  _  | |  _ | |  _ | |  _ d t j | ƒ d } | | d d | d | t j | ƒ |  _ d  S(   Ni   i   (   R   t   maxitert   tolR   t   Gaussiant   cdft   pdft   gamma(   t   selfR   R   R   R   t   tmp(    (    s7   lib/python2.7/site-packages/statsmodels/robust/scale.pyt   __init__O   s    				i    c         C   sÖ   t  j | ƒ } | d k rJ | j d d } t  j | d | ƒ} t } n | j d } | } t } | d k r„ t | d | ƒ} n | } t j	 | | | j ƒ } t j	 | | | j ƒ } |  j
 | | | | | | ƒ S(   s0  
        Compute Huber's proposal 2 estimate of scale, using an optional
        initial value of scale and an optional estimate of mu. If mu
        is supplied, it is not reestimated.

        Parameters
        ----------
        a : array
            1d array
        mu : float or None, optional
            If the location mu is supplied then it is not reestimated.
            Default is None, which means that it is estimated.
        initscale : float or None, optional
            A first guess on scale.  If initscale is None then the standardized
            median absolute deviation of a is used.

        Notes
        -----
        `Huber` minimizes the function

        sum(psi((a[i]-mu)/scale)**2)

        as a function of (mu, scale), where

        psi(x) = np.clip(x, -self.c, self.c)
        i    i   R   N(   R   R   t   Nonet   shapeR	   t   Truet   FalseR   R   t	   unsqueezet   _estimate_both(   R   R   t   mut	   initscaleR   t   nt   est_mut   scale(    (    s7   lib/python2.7/site-packages/statsmodels/robust/scale.pyt   __call__W   s    	c      	   C   s  xçt  |  j ƒ D]Ö} | rš |  j d k rm t j | | |  j | | |  j | ƒ j | ƒ | j | } q¦ t	 j
 | | |  j | | |  j |  j ƒ } n | j ƒ  } t j | | | j ƒ } t j t j | | | ƒ |  j ƒ }	 |	 j | ƒ }
 t j t j |	 | | d | ƒ | |  j | j | |
 |  j d ƒ } t j | | | j ƒ } t j t j t j | | ƒ | |  j ƒ ƒ } t j t j t j | | ƒ | |  j ƒ ƒ } | o¾| sÐ| } | } q | j ƒ  | j ƒ  f Sq Wt d |  j ƒ ‚ d S(   sd  
        Estimate scale and location simultaneously with the following
        pseudo_loop:

        while not_converged:
            mu, scale = estimate_location(a, scale, mu), estimate_scale(a, scale, mu)

        where estimate_location is an M-estimator and estimate_scale implements
        the check used in Section 5.5 of Venables & Ripley
        i   sJ   joint estimation of location and scale failed to converge in %d iterationsN(   R    R   R   R   R   t   clipR   t   sumR   R   t   estimate_locationR   t   squeezeR   R   t
   less_equalR
   t   sqrtR   t   alltruet
   ValueError(   R   R   R#   R   R   R"   R!   t   _t   nmut   subsett   cardt   nscalet   test1t   test2(    (    s7   lib/python2.7/site-packages/statsmodels/robust/scale.pyR   „   s,    +&!+/	N(   t   __name__t
   __module__t   __doc__R   R   R$   R   (    (    (    s7   lib/python2.7/site-packages/statsmodels/robust/scale.pyR   0   s   -t
   HuberScalec           B   s)   e  Z d  Z d d d d „ Z d „  Z RS(   s¦  
    Huber's scaling for fitting robust linear models.

    Huber's scale is intended to be used as the scale estimate in the
    IRLS algorithm and is slightly different than the `Huber` class.

    Parameters
    ----------
    d : float, optional
        d is the tuning constant for Huber's scale.  Default is 2.5
    tol : float, optional
        The convergence tolerance
    maxiter : int, optiona
        The maximum number of iterations.  The default is 30.

    Methods
    -------
    call
        Return's Huber's scale computed as below

    Notes
    --------
    Huber's scale is the iterative solution to

    scale_(i+1)**2 = 1/(n*h)*sum(chi(r/sigma_i)*sigma_i**2

    where the Huber function is

    chi(x) = (x**2)/2       for \|x\| < d
    chi(x) = (d**2)/2       for \|x\| >= d

    and the Huber constant h = (n-p)/n*(d**2 + (1-d**2)*\
            scipy.stats.norm.cdf(d) - .5 - d*sqrt(2*pi)*exp(-0.5*d**2)
    g      @g:Œ0âŽyE>i   c         C   s   | |  _  | |  _ | |  _ d  S(   N(   t   dR   R   (   R   R8   R   R   (    (    s7   lib/python2.7/site-packages/statsmodels/robust/scale.pyR   Ø   s    		c   
         sJ  | | ˆ j  d d ˆ j  d t j ˆ j  ƒ d ˆ j  t j d t j ƒ t j d ˆ j  d ƒ } t ˆ  ƒ } ‡  ‡ f d †  ‰ ‡  ‡ ‡ f d †  } t j | g } d } xŒ t j	 | | d | | ƒ ˆ j
 k rA| ˆ j k  rAt j d | | t j | | d ƒ ƒ | d d ƒ }	 | j |	 ƒ | d 7} q¶ W| d S(   Ni   i   g      à?g      à¿c            s    t  j t  j ˆ  |  ƒ ˆ j ƒ S(   N(   R   t   lessR
   R8   (   t   x(   t   residR   (    s7   lib/python2.7/site-packages/statsmodels/robust/scale.pyt   <lambda>â   t    c            s7   ˆ |  ƒ ˆ  |  d d d ˆ |  ƒ ˆ j  d d S(   Ni   i   (   R8   (   t   s(   R;   R   R/   (    s7   lib/python2.7/site-packages/statsmodels/robust/scale.pyR<   ã   R=   iÿÿÿÿ(   R8   R   R   R   R*   t   pit   expR   t   inft   absR   R   R&   t   append(
   R   t   df_residt   nobsR;   t   hR>   t   chit	   scalehistt   niterR1   (    (   R;   R   R/   s7   lib/python2.7/site-packages/statsmodels/robust/scale.pyR$   Ý   s    G+((   R4   R5   R6   R   R$   (    (    (    s7   lib/python2.7/site-packages/statsmodels/robust/scale.pyR7   µ   s   "(   R6   t   statsmodels.compat.pythonR    t   numpyR   t   scipy.statsR   R   R=   R   t   statsmodels.toolsR   t   ppfR	   R   t   objectR   t   huberR7   t   hubers_scale(    (    (    s7   lib/python2.7/site-packages/statsmodels/robust/scale.pyt   <module>
   s   "‚	<