U
    #ewD                     @   s   d gZ ddlZddlmZmZmZ ddlmZ er:ddl	Z	dd Z
dd Zd	d
 ZG dd deZeeZdd Zde_dd Zdd ZdS )bs    N)have_pandasno_picklingassert_no_pickling)stateful_transformc                 C   s<  zddl m} W n tk
r,   tdY nX ttj|td}|jdksPt|	  t
|}t| } | jdkr| jd dkr| d d df } | jdkstt| t|k st| t|krtdt||d  }tj| jd |ftd}t|D ]6}t|f}d||< || |||f|d d |f< q |S )Nr   )splevz#spline functionality requires scipy)dtype      zksome data points fall outside the outermost knots, and I'm not sure how to handle them. (Patches accepted!))scipy.interpolater   ImportErrornp
atleast_1dasarrayfloatndimAssertionErrorsortintshapeminmaxNotImplementedErrorlenemptyrangezeros)xknotsdegreer   Zn_basesbasisicoefs r#   ^/mounts/lovelace/software/anaconda3/envs/rescript/lib/python3.8/site-packages/patsy/splines.py_eval_bspline_basis   s*    
( r%   c                    s:   t |}t  fdd|jddD }|j|jddS )Nc                    s   g | ]}t  d | qS )d   )r   
percentile).0probr   r#   r$   
<listcomp>A   s   z&_R_compat_quantile.<locals>.<listcomp>C)order)r   r   ravelreshaper   )r   probs	quantilesr#   r*   r$   _R_compat_quantile>   s
    

r2   c                  C   s`   dd } | ddgdd | ddgdd | ddgdd	gdd
g | t tddd	gddg d S )Nc                 S   s   t t| ||std S N)r   allcloser2   r   )r   r)   expectedr#   r#   r$   tF   s    z"test__R_compat_quantile.<locals>.t
      g      ?   g333333?   gffffff?   g@g333333@)listr   )r6   r#   r#   r$   test__R_compat_quantileE   s
    r=   c                   @   s8   e Zd ZdZdd ZdddZd	d
 ZdddZeZ	dS )BSa3  bs(x, df=None, knots=None, degree=3, include_intercept=False, lower_bound=None, upper_bound=None)

    Generates a B-spline basis for ``x``, allowing non-linear fits. The usual
    usage is something like::

      y ~ 1 + bs(x, 4)

    to fit ``y`` as a smooth function of ``x``, with 4 degrees of freedom
    given to the smooth.

    :arg df: The number of degrees of freedom to use for this spline. The
      return value will have this many columns. You must specify at least one
      of ``df`` and ``knots``.
    :arg knots: The interior knots to use for the spline. If unspecified, then
      equally spaced quantiles of the input data are used. You must specify at
      least one of ``df`` and ``knots``.
    :arg degree: The degree of the spline to use.
    :arg include_intercept: If ``True``, then the resulting
      spline basis will span the intercept term (i.e., the constant
      function). If ``False`` (the default) then this will not be the case,
      which is useful for avoiding overspecification in models that include
      multiple spline terms and/or an intercept term.
    :arg lower_bound: The lower exterior knot location.
    :arg upper_bound: The upper exterior knot location.

    A spline with ``degree=0`` is piecewise constant with breakpoints at each
    knot, and the default knot positions are quantiles of the input. So if you
    find yourself in the situation of wanting to quantize a continuous
    variable into ``num_bins`` equal-sized bins with a constant effect across
    each bin, you can use ``bs(x, num_bins - 1, degree=0)``. (The ``- 1`` is
    because one degree of freedom will be taken by the intercept;
    alternatively, you could leave the intercept term out of your model and
    use ``bs(x, num_bins, degree=0, include_intercept=True)``.

    A spline with ``degree=1`` is piecewise linear with breakpoints at each
    knot.

    The default is ``degree=3``, which gives a cubic b-spline.

    This is a stateful transform (for details see
    :ref:`stateful-transforms`). If ``knots``, ``lower_bound``, or
    ``upper_bound`` are not specified, they will be calculated from the data
    and then the chosen values will be remembered and re-used for prediction
    from the fitted model.

    Using this function requires scipy be installed.

    .. note:: This function is very similar to the R function of the same
      name. In cases where both return output at all (e.g., R's ``bs`` will
      raise an error if ``degree=0``, while patsy's will not), they should
      produce identical output given identical input and parameter settings.

    .. warning:: I'm not sure on what the proper handling of points outside
      the lower/upper bounds is, so for now attempting to evaluate a spline
      basis at such points produces an error. Patches gratefully accepted.

    .. versionadded:: 0.2.0
    c                 C   s   i | _ d | _d | _d S r3   )_tmp_degree
_all_knots)selfr#   r#   r$   __init__   s    zBS.__init__N   Fc           	      C   sx   ||||||d}|| j d< t|}|jdkrN|jd dkrN|d d df }|jdkr`td| j dg | d S )N)dfr   r   include_interceptlower_boundupper_boundargsr
   r	   r   z1input to 'bs' must be 1-d, or a 2-d column vectorxs)r?   r   r   r   r   
ValueError
setdefaultappend)	rB   r   rE   r   r   rF   rG   rH   rI   r#   r#   r$   memorize_chunk   s    


zBS.memorize_chunkc                 C   sf  | j }|d }| ` |d dk r0td|d f t|d |d krTtd| jf t|d }|d d kr|d d krtd	|d d
 }|d d k	rR|d | }|d s|d
7 }|dk rtd|d |d |d |d | f |d d k	r.t|d |krRtd|d |d |t|d f n$tdd
|d d
d }t||}|d d k	rh|d }|d d k	r|d }n
t	|}|d d k	r|d }	n
t
|}	||	krtd||	f t|}|jd
krtdt||k rtd|||k  |f t||	kr4td|||	k |	f t||	g| |f}
|
  |d | _|
| _d S )NrI   r   r   z&degree must be greater than 0 (not %r)z"degree must be an integer (not %r)rJ   rE   r   zmust specify either df or knotsr	   rF   zHdf=%r is too small for degree=%r and include_intercept=%r; must be >= %szAdf=%s with degree=%r implies %s knots, but %s knots were providedr
   rG   rH   z#lower_bound > upper_bound (%r > %r)zknots must be 1 dimensionalz1some knot values (%s) fall below lower bound (%r)z1some knot values (%s) fall above upper bound (%r))r?   rK   r   r@   r   concatenater   linspacer2   r   r   r   r   anyr   rA   )rB   tmprI   r   r-   Zn_inner_knotsZknot_quantilesZinner_knotsrG   rH   Z	all_knotsr#   r#   r$   memorize_finish   s    
 










zBS.memorize_finishc           	      C   sT   t || j| j}|s(|d d dd f }trPt|tjtjfrPt|}|j|_|S )Nr	   )	r%   rA   r@   r   
isinstancepandasSeries	DataFrameindex)	rB   r   rE   r   r   rF   rG   rH   r    r#   r#   r$   	transform   s    
zBS.transform)NNrD   FNN)NNrD   FNN)
__name__
__module____qualname____doc__rC   rN   rT   rZ   r   __getstate__r#   r#   r#   r$   r>   M   s   :     
I     
r>   c                  C   s\  ddl m}  ddlm}m}m} |d}d}|d}|| dksHqJ|d7 }|d|}||| }i }	|D ]}
|
dd\}}||	|< qpt|	d	 t	|	d
 t	|	d d}|	d dkrt	|	d \}}||d< ||d< |	d dk|d< t
t	|	d }|d
 d k	r&|jd |d
 ks&t| td||f| |d7 }|d }q8||ksXtd S )Nr   )check_stateful)R_bs_test_xR_bs_test_dataR_bs_num_tests
z--BEGIN TEST CASE--r	   z--END TEST CASE--=r   rE   r   )r   rE   r   zBoundary.knotsNonerG   rH   	interceptTRUErF   outputF)Zpatsy.test_stater`   Zpatsy.test_splines_bs_datara   rb   rc   splitrY   r   evalr   r   r   r   r>   )r`   ra   rb   rc   linesZ	tests_ran	start_idxstop_idxblock	test_datalinekeyvaluekwargslowerupperri   r#   r#   r$   test_bs_compat   s<    






rw   r	   c                  C   sX  t ddd} t| ddgddd}|jd dks4tt d}d|| dk < t |d d df |sftt d}d|| dk| dk @ < t |d d df |stt d}d|| dk< t |d d d	f |stt tddd	gddgdd
ddgddgddggs
tt| ddgddd}t| ddgddd}t |d d dd f |sTtd S )NrO   r	   r7      r   T)r   r   rF   rD   r
   )r   r   rF   F)r   logspacer   r   r   r   array_equal)r   resultZ
expected_0Z
expected_1Z
expected_2Z
result_intZresult_no_intr#   r#   r$   test_bs_0degree-  s.    



r|   c               	   C   s  dd l } tddd}| jtt|ddd | jtt|ddd | tt| t|dddgd	 d
 t|dddgd d
 t|dddgd dd t|dddgd dd | jtt|dddgd d
 | jtt|dddgd	 d
 | jtt|dddgd dd | jtt|dddgd dd | jtt|dddgd d
 | jtt|dddgd d
 | jtt|dddgd dd | jtt|dddgd	 dd | jtt|ddd | jtt|ddd | jtt|ddd | jtt|ddd | jtt|dddd | ttt||fd tt|ddgdt|ddgds:t	| jtt|dgdggd | jtt|ddgd | jtt|ddgdd | jtt|ddgd | jtt|ddgdd d S )Nr   ir7   r8   rD   )rG   )rH   F   )rE   rF   r   T   	   r	   )rE   rF   r   r         )rE   r   rO   g      ?)rG   rH   rx   )r   )r   rH   i)r   rG   )
pytestr   rQ   raisesr   r   rK   column_stackrz   r   )r   r   r#   r#   r$   test_bs_errorsH  s
                                                     *  
          r   )__all__numpyr   
patsy.utilr   r   r   patsy.stater   rV   r%   r2   r=   objectr>   r   rw   slowr|   r   r#   r#   r#   r$   <module>   s   , .-