a
    ߙfbN6                     @   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   s8   |  d t| |W  d    S 1 s*0    Y  d S )NZdiscard_on_copy)Z
index_mode_table_group_by)tablekeys r
   3lib/python3.9/site-packages/astropy/table/groups.pytable_group_by   s    r   c                    s,  ddl m} ddlm} t|tr(|f}t|ttfr|D ]B}| jvrVt	d| j
r:t | jr:t	d|dq: 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||}z(|dur2| }n|jdd}d}	W n( tyl   | }t dv}	Y n0 || }tdg|dd |dd kdgf}
t|
}|	st|dd |dd D ]\}}|||   qȈ  | }||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 zMissing values in key column z are not allowedc                    s   g | ]} | qS r
   r
   ).0keyr   r
   r   
<listcomp>3       z#_table_group_by.<locals>.<listcomp>F)copyTz9Input keys array length {} does not match table length {}NzHKeys input must be string, list, tuple, Table or numpy array, but got {}Z	mergesort)kind)ZDarwinZWindowsgrouped_by_table_colsindicesr	   ) r   r   	serializer   
isinstancestrlisttuplecolnames
ValueErrormaskednpanymask	__class__r   ndarraylenformat	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      s\    




(
"
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 z:Input keys array length {} does not match column length {}TNr   r   )r   r   r   r   r   Zas_arrayr$   r(   r+   r,   r)   r"   r*   r-   r0   r1   r'   r   r5   )columnr	   r   r   r7   r8   r   r;   r
   r
   r   column_group_byq   s$    
(
r=   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_indexrB   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   )rF   r)   r   rD   StopIteration)rC   Ziir9   r:   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   }}z|| ||  }}	W n. t	y }
 zt
d|
W Y d }
~
n
d }
~
0 0 tjt|td}t||	D ]\}}d|||< q|| }|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   )rD   r   intr$   Zintegerr   groupsr	   _keys	Exceptionr+   Zzerosr)   boolr2   r0   Zcumsum_indices)rC   itemrD   r9   r:   r;   Zindices0Zindices1i0si1serrr&   r
   r
   r   __getitem__   s&    zBaseGroups.__getitem__c                 C   s   d| j j d| j dS )N<z	 indices=>)r'   __name__r   rB   r
   r
   r   __repr__   s    zBaseGroups.__repr__c                 C   s   t | jd S rH   )r)   r   rB   r
   r
   r   __len__   s    zBaseGroups.__len__N)rZ   
__module____qualname____doc__propertyrD   rG   rJ   __next__rW   r[   r\   r
   r
   r
   r   r>      s   
r>   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 r?   )r@   rA   rR   rO   )rC   r@   r   r	   r
   r
   r   __init__   s    zColumnGroups.__init__c                 C   s8   | j r| j jjS | jd u r.tdt| jgS | jS d S rE   )rA   rN   r   rR   r$   arrayr)   r@   rB   r
   r
   r   r      s
    

zColumnGroups.indicesc                 C   s   | j r| j jjS | jS d S r?   )rA   rN   r	   rO   rB   r
   r
   r   r	      s    
zColumnGroups.keysc              
      s4  ddl m} | jd d | jdd   }}| jt|}t d} tju } tju }zl|s|sj|sj|r|rtj	
|t| j }	q|rtj	  
|}	n t fddt||D }	W n@ ty }
 z&tdjjjj|
W Y d }
~
n
d }
~
0 0 j|	jjjjjjjjjjd}|S )	Nr   )MaskedColumnr   reduceatc                    s    g | ]\}} || qS r
   r
   )r   r9   r:   funcZpar_colr
   r   r     r   z*ColumnGroups.aggregate.<locals>.<listcomp>z+Cannot aggregate column '{}' with type '{}')datar6   descriptionunitr*   r4   )r<   rd   r   r@   r   hasattrr$   sumZmeanaddre   Zdiffrc   r2   rP   r+   r*   infor6   rL   r'   ri   rj   r4   )rC   rg   rd   rT   rU   r#   re   Zsum_caseZ	mean_caseZvalsrV   r;   r
   rf   r   	aggregate   s<    



$zColumnGroups.aggregatec                 C   s8   t jt| td}t| D ]\}}||||< q| | 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.
        rK   )r$   emptyr)   rQ   	enumerate)rC   rg   r&   iZgroup_columnr
   r
   r   filter  s    zColumnGroups.filter)NN)	rZ   r]   r^   rb   r`   r   r	   ro   rs   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 r?   )rA   rR   rO   )rC   rA   r   r	   r
   r
   r   rb   3  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.
        r4   r   Fr
   )getattrr	   getr!   )rC   r   r
   r
   r   key_colnames8  s    	zTableGroups.key_colnamesc                 C   s(   | j d u rtdt| jgS | j S d S rE   )rR   r$   rc   r)   rA   rB   r
   r
   r   r   D  s    
zTableGroups.indicesc                 C   s   | j dd }g }| j}|j D ]z}|jj| jv r@||}nRz|j	|}W n@ t
y } z(tt|t W Y d}~q"W Y d}~n
d}~0 0 || q"|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   )r4   )r   rA   columnsvaluesrn   r6   rv   ZtakerN   ro   r+   warningswarnr   r   appendr'   r4   )rC   rg   rT   Zout_colsrA   colZnew_colrV   r
   r
   r   ro   K  s    "zTableGroups.aggregatec                 C   s@   t jt| td}| j}t| D ]\}}|||||< q | | 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.
        rK   )r$   rp   r)   rQ   rv   rq   )rC   rg   r&   rv   rr   Zgroup_tabler
   r
   r   rs   n  s
    zTableGroups.filterc                 C   s   | j S r?   )rO   rB   r
   r
   r   r	     s    zTableGroups.keys)NN)
rZ   r]   r^   rb   r`   rv   r   ro   rs   r	   r
   r
   r
   r   r   2  s   


#%)r.   ry   Znumpyr$   indexr   Zastropy.utils.exceptionsr   __all__r   r   r=   r>   r   r   r
   r
   r
   r   <module>   s   \,9\