U
    KvfW                  U   @   s8  d dl mZ d dlZd dlmZ d dlmZmZmZ d dl	m
Z
mZ d dlmZ d dlmZmZ d dlmZmZ d	d
dgZG dd	 d	eZeg ZG dd deZdd ZG dd
 d
eZdd Zdd ZG dd deZdd Zdd Zdd Zdd Zd d! Z d"d# Z!d$d% Z"d&d' Z#d(d) Z$d*d+ Z%d,d- Z&d.d/ Z'd0d1 Z(d2d3 Z)d4d5 Z*d6d7 Z+G d8d9 d9eZ,d:g fd:g fd:g fd:d;gfd:g fd<g fd<g fd:g fd:g fd<g fd:g fd<g fd:g fd<g fd:d;gfd<d;gfd<d;gfd:d;gfd:g fd:d;d=gfd:d;d=gfd:d;d=gfd:d;d=gfd:d;d=gfd:d;gfd:d;d=gfd:d;d>gfd:d;gfd:d;d?d@gfd:d;dAgfd:dBgfd:dBgfd:dBdCgfd:dCdDgfd:dBgfd:d@dCdBgfd:dCgfd:d=dDdCgfd:g fd:g fd:g fd:g fd:d;d=dBgfd:d;d=dBgfd:d;d=d@dBdCgfd:d;d=d@dCdDgfd:d;d=dBgfd:d@dCd;d=dBgfd:d;d@dCgfd:d=dDd;d@dCgfd:d;dBgfd:d;d=dEgfd:d=dDd;dCgfd:d;dBdCgfd:d;gfd:d;d=d@dFdBdCdGdDdHdIg
fd:d;d=d@dFdBdCdGdDdHdIdEdJdKdLgfd:d;gfd:d;d=gfd:d;d=dBgfd<d;d=dBgfd<g fd:d;d=gfd:g d:d;d=gfd<dMgd:d;d=gfd<dMgd:d;d=gfd<dMdNdOgd:d;d=gfd<g d:g fd:dMgd:d;d=gfd:d;d=d@dDgfd:d;d=dBd@gfd:d=dBgfd:d;d=dDgfd:d;dBd@gfd:d;dDdEgfd:dBd@dEgfd:g fd<g fd:g fd<g fd:d;gfd:d;gfd:d;gfd<g fdPTZ-dQdRdSdTdUdVdWdXdYdZd[d\d]d^d_d`dadbdcdddedfdgdhdidjdkdldmdndodpdqdrdsg#Z.dtdu Z/dvdw Z0dxdy Z1dzd{ Z2d|d} Z3dS )~    )print_functionN
PatsyError)	ParseNodeTokenparse_formula)EvalEnvironment
EvalFactor)uniqueify_list)repr_pretty_delegaterepr_pretty_impl)no_picklingassert_no_picklingTerm	ModelDesc	INTERCEPTc                   @   sH   e Zd ZdZdd Zdd Zdd Zdd	 ZeZ	d
d Z
dd ZeZdS )r   a  The interaction between a collection of factor objects.

    This is one of the basic types used in representing formulas, and
    corresponds to an expression like ``"a:b:c"`` in a formula string.
    For details, see :ref:`formulas` and :ref:`expert-model-specification`.

    Terms are hashable and compare by value.

    Attributes:
    
    .. attribute:: factors

       A tuple of factor objects.
    c                 C   s   t t|| _d S N)tupler
   factors)selfr    r   ./tmp/pip-unpacked-wheel-68fdvdus/patsy/desc.py__init__+   s    zTerm.__init__c                 C   s   t |tot|jt| jkS r   )
isinstancer   	frozensetr   r   otherr   r   r   __eq__.   s    
zTerm.__eq__c                 C   s
   | |k S r   r   r   r   r   r   __ne__2   s    zTerm.__ne__c                 C   s   t tt| jfS r   )hashr   r   r   r   r   r   r   __hash__5   s    zTerm.__hash__c                 C   s    |rt t|| t| jg d S r   )AssertionErrorr   listr   r   pcycler   r   r   _repr_pretty_9   s    zTerm._repr_pretty_c                 C   s$   | j rddd | j D S dS dS )z+Return a human-readable name for this term.:c                 S   s   g | ]}|  qS r   )name).0fr   r   r   
<listcomp>@   s     zTerm.name.<locals>.<listcomp>	InterceptN)r   joinr    r   r   r   r)   =   s    z	Term.nameN)__name__
__module____qualname____doc__r   r   r   r!   r   __repr__r'   r)   r   __getstate__r   r   r   r   r      s   c                   @   s   e Zd Zdd Zdd ZdS )_MockFactorc                 C   s
   || _ d S r   _name)r   r)   r   r   r   r   I   s    z_MockFactor.__init__c                 C   s   | j S r   r6   r    r   r   r   r)   L   s    z_MockFactor.nameN)r/   r0   r1   r   r)   r   r   r   r   r5   H   s   r5   c                  C   s   t dddgjdkstt ddgt ddgks4ttt ddgtt ddgksXttd} td}t | |g dkstt || g dkstt g  dksttt g  d S )	N      )r8   r9   aba:bzb:ar-   )r   r   r"   r   r5   r)   r   )f1f2r   r   r   	test_TermO   s    $r?   c                   @   s<   e Zd ZdZdd ZeZdd Zdd Ze	dd	 Z
eZd
S )r   a  A simple container representing the termlists parsed from a formula.

    This is a simple container object which has exactly the same
    representational power as a formula string, but is a Python object
    instead. You can construct one by hand, and pass it to functions like
    :func:`dmatrix` or :func:`incr_dbuilder` that are expecting a formula
    string, but without having to do any messy string manipulation. For
    details see :ref:`expert-model-specification`.

    Attributes:

    .. attribute:: lhs_termlist
                   rhs_termlist

       Two termlists representing the left- and right-hand sides of a
       formula, suitable for passing to :func:`design_matrix_builders`.
    c                 C   s   t || _t || _d S r   )r
   lhs_termlistrhs_termlist)r   r@   rA   r   r   r   r   m   s    
zModelDesc.__init__c                 C   s&   |rt t|| g d| jfd| jfgS )Nr@   rA   )r"   r   r@   rA   r$   r   r   r   r'   r   s    zModelDesc._repr_pretty_c                    s   dd  d  fdd| jD }|r0|d7 }n|d7 }| jtgkrR| t7 }n>g }t| jkrj|d | fd	d| jD 7 }|d |7 }|S )
a  Returns a human-readable representation of this :class:`ModelDesc`
        in pseudo-formula notation.

        .. warning:: There is no guarantee that the strings returned by this
           function can be parsed as formulas. They are best-effort
           descriptions intended for human users. However, if this ModelDesc
           was created by parsing a formula, then it should work in
           practice. If you *really* have to.
        c                 S   s   | t krdS |  S d S )N1)r   r)   )termr   r   r   	term_code   s    z%ModelDesc.describe.<locals>.term_codez + c                    s   g | ]} |qS r   r   r*   rC   rD   r   r   r,      s     z&ModelDesc.describe.<locals>.<listcomp>z ~ z~ 0c                    s   g | ]}|t kr |qS r   r   rE   rF   r   r   r,      s    )r.   r@   rA   r   append)r   resultZ
term_namesr   rF   r   describey   s    



zModelDesc.describec                 C   s:   t |tr|}nt|}t j|dd}t || s6t|S )a$  Construct a :class:`ModelDesc` from a formula string.

        :arg tree_or_string: A formula string. (Or an unevaluated formula
          parse tree, but the API for generating those isn't public yet. Shh,
          it can be our secret.)
        :returns: A new :class:`ModelDesc`.
        F)require_evalexpr)r   r   r   	Evaluatorevalr"   )clsZtree_or_stringtreevaluer   r   r   from_formula   s    	
zModelDesc.from_formulaN)r/   r0   r1   r2   r   r   r3   r'   rK   classmethodrR   r   r4   r   r   r   r   r   [   s   
c                  C   s   t d} t d}ttt| ggt| gt| |gg}|jtt| ggksNt|jt| gt| |ggksntt|  | dkstt	| tg g  dkstttgg  dkstttgtg dkstttgtt|gg dkstd S )Nr:   r;   z1 + a ~ 0 + a + a:bz~ 0z1 ~ 0z1 ~ 1z1 ~ b)
r5   r   r   r   r@   r"   rA   printrK   r   )r=   r>   mr   r   r   test_ModelDesc   s    & rV   c                  C   sV   dt dfD ]D} t| }|jttdggks4t|jtttdggkstqd S )Nzy ~ xyx)	r   r   rR   r@   r   r	   r"   rA   r   )inputZmdr   r   r   test_ModelDesc_from_formula   s    
rZ   c                   @   s(   e Zd ZdZdd ZeZdd ZeZ	dS )IntermediateExprzFThis class holds an intermediate result while we're evaluating a tree.c                 C   sD   || _ || _|| _tt|| _| j r0| js0t| j r@| jr@td S r   )	interceptintercept_originintercept_removedr   r
   termsr"   )r   r\   r]   r^   r_   r   r   r   r      s    
zIntermediateExpr.__init__c                 C   s$   |rt t|| | j| j| j| jgS r   )r"   r   r\   r]   r^   r_   r$   r   r   r   _pretty_repr_   s     zIntermediateExpr._pretty_repr_N)
r/   r0   r1   r2   r   r   r3   r`   r   r4   r   r   r   r   r[      s
   	r[   c                 C   s   | rt f| S |S d S r   rH   )Zdoitr_   r   r   r   _maybe_add_intercept   s    
ra   c                    sv    fdd|j D }t|dkr6|dtdd dg  t|dksFttt|d j|d jt|d j	 |d jS )Nc                    s   g | ]}  |qS r   rN   r*   arg	evaluatorr   r   r,      s     z#_eval_any_tilde.<locals>.<listcomp>r8   r   FTr9   )
argsleninsertr[   r"   r   ra   r\   r_   r^   rf   rP   exprsr   re   r   _eval_any_tilde   s    rl   c                 C   s~   |  |jd }|jd jdkr0tdd d|jS |  |jd }|jr^td|jd|j|j S t|j|j|j|j|j S d S )Nr   r8   ZEROFTrN   rg   typer[   r_   r\   r]   r^   )rf   rP   	left_expr
right_exprr   r   r   _eval_binary_plus   s    


rr   c                    s   |  |jd }|jd jdkr6td|jd d|jS |jd jdkrVtdd d|jS |  |jd   fdd|jD } jrtdd d|S t|j|j|j|S d S )	Nr   r8   rm   TFONEc                    s   g | ]}| j kr|qS r   )r_   rE   rq   r   r   r,     s    
z&_eval_binary_minus.<locals>.<listcomp>rn   )rf   rP   rp   r_   r   rt   r   _eval_binary_minus   s     ru   c                 C   s   | j rtd| jd S )Nz1intercept term cannot interact with anything else)r\   r   r]   )exprr   r   r   _check_interactable  s    rw   c                 C   sV   | |fD ]}t | qg }| jD ]&}|jD ]}|t|j|j  q*q tdd d|S )NF)rw   r_   rI   r   r   r[   )rp   rq   rv   r_   Zl_termZr_termr   r   r   _interaction  s    


rx   c                    s<    fdd|j D }tdd d|d j|d j t| j S )Nc                    s   g | ]}  |qS r   rb   rc   re   r   r   r,     s     z%_eval_binary_prod.<locals>.<listcomp>Fr   r8   )rg   r[   r_   rx   rj   r   re   r   _eval_binary_prod  s    ry   c                 C   s   |  |jd }|  |jd }t|j}t| g }|jD ]}|t|j7 }q<tdd dt|g}|tt||j7 }tdd d|S )Nr   r8   F)	rN   rg   r#   r_   rw   r   r[   r   rx   )rf   rP   rp   rq   r_   Zleft_factorsrC   Zleft_combined_exprr   r   r   _eval_binary_div(  s    

rz   c                    s    fdd|j D }t| S )Nc                    s   g | ]}  |qS r   rb   rc   re   r   r   r,   8  s     z)_eval_binary_interact.<locals>.<listcomp>)rg   rx   rj   r   re   r   _eval_binary_interact7  s    r{   c                 C   s   |  |jd }t| d}|jd jdkr\|jd jj}zt|}W n tk
rZ   Y nX |dk rttd|jd |j	}|}t
t|j	|}td|D ]}t||}||j	 }qtdd d|S )Nr   r8   )rs   NUMBERz '**' requires a positive integerF)rN   rg   rw   ro   tokenextraint
ValueErrorr   r_   minrh   rangerx   r[   )rf   rP   rp   powerrv   Z	all_termsZbig_exprir   r   r   _eval_binary_power;  s$    
r   c                 C   s   |  |jd S )Nr   )rN   rg   rf   rP   r   r   r   _eval_unary_plusP  s    r   c                 C   sL   |j d jdkr td|jdg S |j d jdkr>tdd dg S td|d S )Nr   rm   TFrs   z)Unary minus can only be applied to 1 or 0)rg   ro   r[   originr   r   r   r   r   _eval_unary_minusS  s
    r   c                 C   s   t dd dg S )NFT)r[   r   r   r   r   
_eval_zero[  s    r   c                 C   s   t d|jdg S )NTF)r[   r   r   r   r   r   	_eval_one^  s    r   c                 C   s   t d|d S )Nz4numbers besides '0' and '1' are only allowed with **r   r   r   r   r   _eval_numbera  s    r   c                 C   s(   t |jj|jd}tdd dt|ggS )N)r   F)r	   r~   r   r   r[   r   )rf   rP   Zfactorr   r   r   _eval_python_expre  s    r   c                   @   s&   e Zd Zdd Zdd Zd	ddZdS )
rM   c                 C   s   i | _ | ddt | ddt | ddt | ddt | ddt | ddt | ddt | d	dt | ddt	 | ddt
 | d
dt | ddt | ddt | ddt i | _d S )N~r9   r8   +-*/r(   z**rm   r   rs   r}   ZPYTHON_EXPR)_evaluatorsadd_oprl   rr   ru   ry   rz   r{   r   r   r   r   r   r   r   stashr    r   r   r   r   j  s     zEvaluator.__init__c                 C   s   || j ||f< d S r   )r   )r   oparityrf   r   r   r   r     s    zEvaluator.add_opTc                 C   s   d }t |tst|jt|jf}|| jkr@td|jf |j| j| | |}|r~t |t	s~t |t
rttd|n
td||S )Nz/I don't know how to evaluate this '%s' operatorz2~ can only be used once, and only at the top levelzBcustom operator returned an object that I don't know how to handle)r   r   r"   ro   rh   rg   r   r   r~   r[   r   )r   rP   rL   rJ   keyr   r   r   rN     s&    

zEvaluator.evalN)T)r/   r0   r1   r   r   rN   r   r   r   r   rM   i  s   rM   Tr:   Fr;   znp.log(a, base=10)zI(b)czI(b + c))r:   r;   )r:   r   )r;   r   )r:   r;   r   d)r:   r   )r;   r   )r   r   )r:   r;   r   )r:   r   r   )r;   r   r   rW   z)rW   r   )T  z 
 r:   rB   rG   z- 1z- 0z+ 1z+ 0z0 + 1z1 + 0z1 - 0z0 - 1z1 + az0 + aza - 1za - 0z1 - aa + bz(a + b)za + ((((b))))za + ((((+b))))za + ((((b - a))))z	a + a + aza + (b - a)za + np.log(a, base=10)z0a + np.log(a, base=10) - np . log(a , base = 10)za + (I(b) + c)za + I(b + c)r<   za:b:az	a:(b + c)z	(a + b):cz	a:(b - c)zc + a:c + a:(b - c)z	(a - b):czb + b:c + (a - b):cz	a:b - a:bz	a:b - b:az1 - (a + b)za + b - (a + b)za * bz	a * b * aza * (b + c)z(a + b) * cza * (b - c)zc + a:c + a * (b - c)z(a - b) * czb + b:c + (a - b) * cza/bz	(a + b)/czb + b:c + (a - b)/cz	a/(b + c)za ** 2z(a + b + c + d) ** 2z(a + b + c + d) ** 3za + +az~ a + bz~ a*bz	~ a*b + 0z~ -1z	0 ~ a + bz	1 ~ a + bz	y ~ a + bz0 + y ~ a + bz0 + y * z ~ a + bz-1 ~ 1z1 + y ~ a + bz	a + b * cz	a * b + cz	a * b - az	a + b / cz	a / b + cza*b:cza:b*cz~ 1 + 1 + 0 + 1z~ 0 + 1 + 0z~ 0 - 1 - 1 + 0 + 1z~ 1 - 1z~ 0 + a + 1z~ 1 + (a + 0)z~ 0 + (a + 1)z~ 1 - (a + 1)za <+>za + <(>z
b + <(-a)>za:<1>z(a + <1>)*bza + <2>z	a + <1.0>za ** <b>za ** <(1 + 1)>z
a ** <1.5>za + b <# asdf>z<)>za + <)>z<*> aza + <*>za + <foo[bar>za + <foo{bar>za + <foo(bar>z
a + <[bar>z
a + <{bar>za + <{bar[]>za + foo<]>barza + foo[]<]>barza + foo{}<}>barza + foo<)>barza + b<)>z(a) <.>z<(>a + bz<y ~ a> ~ bzy ~ <(a ~ b)>z	<~ a> ~ bz~ <(a ~ b)>z1 + <-(a + b)>z<- a>za + <-a**2>c                 C   s~   |rdg| }t | t |ks"tt| |D ]L\}}t|trlt|trN|f}|jtdd |D ksxtq,||ks,tq,d S )Nr   c                 S   s   g | ]}t |qS r   )r	   )r*   sr   r   r   r,   Q  s     z'_assert_terms_match.<locals>.<listcomp>)rh   r"   zipr   r   strr   r   )r_   Zexpected_intercept	expectedsrC   expectedr   r   r   _assert_terms_matchI  s    


r   c                 C   s~   t | D ]n\}}t|dkr*dg f| }t|}tt| t| t| |\}}}}t|j|| t|j	|| q
d S )Nr9   F)
six	iteritemsrh   r   rR   rT   reprr   r@   rA   )testscoderJ   Z
model_descZlhs_interceptr@   Zrhs_interceptrA   r   r   r   _do_eval_formula_testsU  s     
  r   c                   C   s   t t d S r   )r   _eval_testsr   r   r   r   test_eval_formulac  s    r   c                  C   s"   ddl m}  dd }| |t d S )Nr   )_parsing_error_testc                 S   s
   t | S r   )r   rR   )Zformular   r   r   <lambda>h      z3test_eval_formula_error_reporting.<locals>.<lambda>)patsy.parse_formular   _eval_error_tests)r   Zparse_fnr   r   r   !test_eval_formula_error_reportingf  s    r   c                  C   s^   ddl m}  td}|jd jd j| dddks8t|jd jd j| dddksZtd S )Nr   )Originr   r8   r9         )Zpatsy.originr   r   rR   rA   r   r   r"   )r   descr   r   r   test_formula_factor_origink  s    


r   )4
__future__r   r   Zpatsyr   r   r   r   r   Z
patsy.evalr   r	   Z
patsy.utilr
   r   r   r   r   __all__objectr   r   r5   r?   r   rV   rZ   r[   ra   rl   rr   ru   rw   rx   ry   rz   r{   r   r   r   r   r   r   r   rM   r   r   r   r   r   r   r   r   r   r   r   <module>	   sb  
*P	6











    
      



t8