B
    q\6                 @   s   d dl Z d dlZd dlZddlmZ d dlmZ ddgZdd Z	d	d
 Z
dd ZG dd dZG dd deZG dd deZdS )    N   )get_index_by_names)AstropyUserWarningTableGroupsColumnGroupsc          	   C   s    |  d t| |S Q R X d S )NZdiscard_on_copy)Z
index_mode_table_group_by)tablekeys r
   3lib/python3.7/site-packages/astropy/table/groups.pytable_group_by   s    r   c                s4  ddl m} ddlm} t|tr(|f}t|ttfrxH|D ]@}| jkrXt	d
| jr<t | jr<t	d
|q<W  j fdd|D dd	}t |}d
}nXt|tj|fr|}t|t krt	d
t|t d}d}ntd
t||st||r||}y(|dk	r4| }n|jdd}d
}	W n* tk
rp   | }t dk}	Y nX || }td
g|dd |dd kd
gf}
t|
}|	sx8t|dd |dd D ]\}}|||   qW   | }||dd  }t||r ||jd< t|||d|_|S )a2  
    Get groups for ``table`` on specified ``keys``.

    Parameters
    ----------
    table : `Table`
        Table to group
    keys : str, list of str, `Table`, or Numpy array
        Grouping key specifier

    Returns
    -------
    grouped_table : Table object with groups attr set accordingly
    r   )Table)_represent_mixins_as_columnsz$Table does not have key column {0!r}z2Missing values in key column {0!r} are not allowedc                s   g | ]} | qS r
   r
   ).0key)r   r
   r   
<listcomp>3   s    z#_table_group_by.<locals>.<listcomp>F)copyTz;Input keys array length {0} does not match table length {1}NzIKeys input must be string, list, tuple, Table or numpy array, but got {0}Z	mergesort)Zkind)ZDarwinZWindowsgrouped_by_table_cols)indicesr	   ) r   r   	serializer   
isinstancestrlisttuplecolnames
ValueErrorformatmaskednpanymask	__class__r   ndarraylen	TypeErrortypeZsorted_dataargsortplatformsystemconcatenateflatnonzerozipsortmetar   _groups)r   r	   r   r   nameZ
table_keysZtable_indexr   idx_sortZstable_sortdiffsr   i0i1outZout_keysr
   )r   r   r      sX    





(
$
r   c             C   s   ddl m} ddlm} t||r2||}| }t|tjsPtd	t
|t|t| krxtd	t|t| | }|| }tdg|dd |dd kdgf}t|}| | | }t||||dd  d	|_|S )
a=  
    Get groups for ``column`` on specified ``keys``

    Parameters
    ----------
    column : Column object
        Column to group
    keys : Table or Numpy array of same length as col
        Grouping key specifier

    Returns
    -------
    grouped_column : Column object with groups attr set accordingly
    r   )r   )r   z+Keys input must be numpy array, but got {0}z<Input keys array length {0} does not match column length {1}TNr   )r   r	   )r   r   r   r   r   Zas_arrayr   r#   r%   r   r&   r$   r   r'   r*   r+   r"   r   r/   )columnr	   r   r   r1   r2   r   r5   r
   r
   r   column_group_byq   s$    
(
r7   c               @   sH   e Zd ZdZedd Zdd Zdd ZeZdd	 Z	d
d Z
dd ZdS )
BaseGroupsa4  
    A class to represent groups within a table of heterogeneous data.

      - ``keys``: key values corresponding to each group
      - ``indices``: index values in parent table or column corresponding to group boundaries
      - ``aggregate()``: method to create new table by aggregating within groups
    c             C   s   t | tr| jS | jS )N)r   r   parent_columnparent_table)selfr
   r
   r   parent   s    zBaseGroups.parentc             C   s
   d| _ | S )Nr   )_iter_index)r;   r
   r
   r   __iter__   s    zBaseGroups.__iter__c             C   sV   | j }|t| jd k rN| j| | j|d   }}|  j d7  _ | j|| S td S )Nr   )r=   r$   r   r<   StopIteration)r;   Ziir3   r4   r
   r
   r   next   s    zBaseGroups.nextc             C   s  | j }t|ttjfrN| j| | j|d   }}||| }|jj| |j_n| jd d | jdd   }}y|| ||  }}	W n t	k
r   t
dY nX tjt|td}
x"t||	D ]\}}d|
||< qW ||
 }|jj| |j_tdgt|	| g|j_|S )Nr   r   zHIndex item for groups attribute must be a slice, numpy mask or int array)dtypeTr   )r<   r   intr   Zintegerr   groupsr	   _keys	Exceptionr%   Zzerosr$   boolr,   r*   Zcumsum_indices)r;   itemr<   r3   r4   r5   Zindices0Zindices1i0si1sr!   r
   r
   r   __getitem__   s"    zBaseGroups.__getitem__c             C   s   d | jj| jS )Nz<{0} indices={1}>)r   r"   __name__r   )r;   r
   r
   r   __repr__   s    zBaseGroups.__repr__c             C   s   t | jd S )Nr   )r$   r   )r;   r
   r
   r   __len__   s    zBaseGroups.__len__N)rL   
__module____qualname____doc__propertyr<   r>   r@   __next__rK   rM   rN   r
   r
   r
   r   r8      s   r8   c               @   s>   e Zd ZdddZedd Zedd Zdd	 Zd
d ZdS )r   Nc             C   s   || _ |j| _|| _|| _d S )N)r9   r:   rG   rD   )r;   r9   r   r	   r
   r
   r   __init__   s    zColumnGroups.__init__c             C   s8   | j r| j jjS | jd kr.tdt| jgS | jS d S )Nr   )r:   rC   r   rG   r   arrayr$   r9   )r;   r
   r
   r   r      s
    

zColumnGroups.indicesc             C   s   | j r| j jjS | jS d S )N)r:   rC   r	   rD   )r;   r
   r
   r   r	      s    
zColumnGroups.keysc                s   ddl m} | jd d | jdd   }}| jt|}t d} tjk} tjk}yl|s|sj|sj|r|rtj	
|t| j }	q|rtj	  
|}	n t fddt||D }	W n, tk
r   tdjjjjY nX j|	jjjjjjjjjjd}
|
S )	Nr   )MaskedColumnr   reduceatc                s    g | ]\}} || qS r
   r
   )r   r3   r4   )funcpar_colr
   r   r     s    z*ColumnGroups.aggregate.<locals>.<listcomp>z-Cannot aggregate column '{0}' with type '{1}')datar0   descriptionunitr   r.   )r6   rV   r   r9   r   hasattrr   sumZmeanaddrW   ZdiffrU   r,   rE   r%   r   infor0   rA   r"   r[   r\   r.   )r;   rX   rV   rI   rJ   r   rW   Zsum_caseZ	mean_caseZvalsr5   r
   )rX   rY   r   	aggregate   s4    



$zColumnGroups.aggregatec             C   s<   t jt| td}x t| D ]\}}||||< qW | | S )a  
        Filter groups in the Column based on evaluating function ``func`` on each
        group sub-table.

        The function which is passed to this method must accept one argument:

        - ``column`` : `Column` object

        It must then return either `True` or `False`.  As an example, the following
        will select all column groups with only positive values::

          def all_positive(column):
              if np.any(column < 0):
                  return False
              return True

        Parameters
        ----------
        func : function
            Filter function

        Returns
        -------
        out : Column
            New column with the aggregated rows.
        )rA   )r   emptyr$   rF   	enumerate)r;   rX   r!   iZgroup_columnr
   r
   r   filter  s    zColumnGroups.filter)NN)	rL   rO   rP   rT   rR   r   r	   ra   re   r
   r
   r
   r   r      s
   
 c               @   sJ   e Zd ZdddZedd Zedd Zdd	 Zd
d Zedd Z	dS )r   Nc             C   s   || _ || _|| _d S )N)r:   rG   rD   )r;   r:   r   r	   r
   r
   r   rT   4  s    zTableGroups.__init__c             C   s&   t | jdi dd}|r"| jjS dS )z^
        Return the names of columns in the parent table that were used for grouping.
        r.   r   Fr
   )getattrr	   getr   )r;   r   r
   r
   r   key_colnames9  s    	zTableGroups.key_colnamesc             C   s(   | j d krtdt| jgS | j S d S )Nr   )rG   r   rU   r$   r:   )r;   r
   r
   r   r   E  s    
zTableGroups.indicesc       	      C   s   | j dd | j dd  }}g }| j}x||j D ]n}|jj| jkrR||}nFy|j	|}W n4 t
k
r } ztt|t w4W dd}~X Y nX || q4W |j||jdS )a  
        Aggregate each group in the Table into a single row by applying the reduction
        function ``func`` to group values in each column.

        Parameters
        ----------
        func : function
            Function that reduces an array of values to a single value

        Returns
        -------
        out : Table
            New table with the aggregated rows.
        Nr   r   )r.   )r   r:   columnsvaluesr`   r0   rh   ZtakerC   ra   r%   warningswarnr   r   appendr"   r.   )	r;   rX   rI   rJ   Zout_colsr:   colZnew_colerrr
   r
   r   ra   L  s    zTableGroups.aggregatec             C   sD   t jt| td}| j}x"t| D ]\}}|||||< q"W | | S )a  
        Filter groups in the Table based on evaluating function ``func`` on each
        group sub-table.

        The function which is passed to this method must accept two arguments:

        - ``table`` : `Table` object
        - ``key_colnames`` : tuple of column names in ``table`` used as keys for grouping

        It must then return either `True` or `False`.  As an example, the following
        will select all table groups with only positive values in the non-key columns::

          def all_positive(table, key_colnames):
              colnames = [name for name in table.colnames if name not in key_colnames]
              for colname in colnames:
                  if np.any(table[colname] < 0):
                      return False
              return True

        Parameters
        ----------
        func : function
            Filter function

        Returns
        -------
        out : Table
            New table with the aggregated rows.
        )rA   )r   rb   r$   rF   rh   rc   )r;   rX   r!   rh   rd   Zgroup_tabler
   r
   r   re   o  s
    zTableGroups.filterc             C   s   | j S )N)rD   )r;   r
   r
   r   r	     s    zTableGroups.keys)NN)
rL   rO   rP   rT   rR   rh   r   ra   re   r	   r
   r
   r
   r   r   3  s   
#%)r(   rk   Znumpyr   indexr   Zastropy.utils.exceptionsr   __all__r   r   r7   r8   r   r   r
   r
   r
   r   <module>   s   \-9\