a
    �ù»j÷L  ã                   @   sØ   d Z ddlZddlZddlmZ ddlmZ ddlmZ ddl	Z
ddlZddlmZ ddlmZ dd	lmZmZ dd
lmZ ddlmZ eeedœdd„Zeee
jdœdd„Zdd„ Zddd„Zddd„Zddd„ZdS )z9Implementation of ARFF parsers: via LIAC-ARFF and pandas.é    N)ÚOrderedDict)Ú	Generator)ÚListé   )Ú_arff)ÚArffSparseDataType)Úchunk_generatorÚget_chunk_n_rows)Úcheck_pandas_support)Ú	pd_fillna)Ú	arff_dataÚinclude_columnsÚreturnc                 C   s€   t ƒ t ƒ t ƒ f}dd„ t|ƒD ƒ}t| d | d | d ƒD ]@\}}}||v r:|d  |¡ |d  |¡ |d  || ¡ q:|S )a™  Obtains several columns from sparse ARFF representation. Additionally,
    the column indices are re-labelled, given the columns that are not
    included. (e.g., when including [1, 2, 3], the columns will be relabelled
    to [0, 1, 2]).

    Parameters
    ----------
    arff_data : tuple
        A tuple of three lists of equal size; first list indicating the value,
        second the x coordinate and the third the y coordinate.

    include_columns : list
        A list of columns to include.

    Returns
    -------
    arff_data_new : tuple
        Subset of arff data with only the include columns indicated by the
        include_columns argument.
    c                 S   s   i | ]\}}||“qS © r   ©Ú.0Z	array_idxZ
column_idxr   r   úCE:\soccer\ml_env\Lib\site-packages\sklearn/datasets/_arff_parser.pyÚ
<dictcomp>.   s   z)_split_sparse_columns.<locals>.<dictcomp>r   é   r   )ÚlistÚ	enumerateÚzipÚappend)r   r   Zarff_data_newÚreindexed_columnsÚvalÚrow_idxÚcol_idxr   r   r   Ú_split_sparse_columns   s    ÿ"r   c           	      C   s~   t | d ƒd }|t|ƒf}dd„ t|ƒD ƒ}tj|tjd�}t| d | d | d ƒD ]"\}}}||v rV||||| f< qV|S )Nr   c                 S   s   i | ]\}}||“qS r   r   r   r   r   r   r   @   s   z)_sparse_data_to_array.<locals>.<dictcomp>©Údtyper   r   )ÚmaxÚlenr   ÚnpÚemptyÚfloat64r   )	r   r   Únum_obsZy_shaper   Úyr   r   r   r   r   r   Ú_sparse_data_to_array9   s    ÿ"r'   c                 C   sD   | | }t |ƒdkr| | }nt |ƒdkr8| |d  }nd}||fS )a  Post process a dataframe to select the desired columns in `X` and `y`.

    Parameters
    ----------
    frame : dataframe
        The dataframe to split into `X` and `y`.

    feature_names : list of str
        The list of feature names to populate `X`.

    target_names : list of str
        The list of target names to populate `y`.

    Returns
    -------
    X : dataframe
        The dataframe containing the features.

    y : {series, dataframe} or None
        The series or dataframe containing the target.
    r   r   r   N)r!   )ÚframeZfeature_namesZtarget_namesÚXr&   r   r   r   Ú_post_process_frameK   s    
r*   c           "         sœ  dd„ }|| ƒ}|dkrt jnt j}|dk }	t j|||	d�}
|| ‰‡fdd„|
d D ƒ‰ |dk�rÂtd	ƒ}t|
d ƒ}t| ¡ ƒ}t|
d
 ƒ}|j	|g|dd�}|j
dd� ¡ }t|ƒ}‡fdd„|D ƒ}|| g}t|
d
 |ƒD ]}| |j	||dd�| ¡ qæt|ƒdk�r,|d  |d j¡|d< |j|dd�}t||ƒ}~~i }|jD ]P}ˆ| d }| ¡ dk�rzd||< n&| ¡ dk�r’d||< n|j| ||< �qR| |¡}t|||ƒ\}‰�n¸|
d
 }‡fdd„|D ƒ}‡fdd„|D ƒ}t|tƒ�rt|du �rtdƒ‚|d dk�r d}n|d |d  }tjtj |¡d|d �}|j|Ž }|dd…|f }|dd…|f ‰n€t|t ƒ�rât!||ƒ}t"|d ƒd }|t|ƒf} t#j$j%|d |d |d ff| tj&d!�}| '¡ }t(||ƒ‰ntd"t)|ƒ› �ƒ‚‡ fd#d$„|D ƒ}!|!�sn<t*|!ƒ�r8t +‡ ‡fd%d„t,|ƒD ƒ¡‰nt-|!ƒ�rJtd&ƒ‚ˆj.d dk�rfˆ d'¡‰nˆj.d dk�rzd‰|dk�r�|ˆ|dfS |ˆdˆ fS )(a  ARFF parser using the LIAC-ARFF library coded purely in Python.

    This parser is quite slow but consumes a generator. Currently it is needed
    to parse sparse datasets. For dense datasets, it is recommended to instead
    use the pandas-based parser, although it does not always handles the
    dtypes exactly the same.

    Parameters
    ----------
    gzip_file : GzipFile instance
        The file compressed to be read.

    output_arrays_type : {"numpy", "sparse", "pandas"}
        The type of the arrays that will be returned. The possibilities ara:

        - `"numpy"`: both `X` and `y` will be NumPy arrays;
        - `"sparse"`: `X` will be sparse matrix and `y` will be a NumPy array;
        - `"pandas"`: `X` will be a pandas DataFrame and `y` will be either a
          pandas Series or DataFrame.

    columns_info : dict
        The information provided by OpenML regarding the columns of the ARFF
        file.

    feature_names_to_select : list of str
        A list of the feature names to be selected.

    target_names_to_select : list of str
        A list of the target names to be selected.

    Returns
    -------
    X : {ndarray, sparse matrix, dataframe}
        The data matrix.

    y : {ndarray, dataframe, series}
        The target.

    frame : dataframe or None
        A dataframe containing both `X` and `y`. `None` if
        `output_array_type != "pandas"`.

    categories : list of str or None
        The names of the features that are categorical. `None` if
        `output_array_type == "pandas"`.
    c                 s   s   | D ]}|  d¡V  qd S )Núutf-8)Údecode)Ú	gzip_fileÚliner   r   r   Ú_io_to_generator¢   s    z+_liac_arff_parser.<locals>._io_to_generatorÚsparseÚpandas)Úreturn_typeÚencode_nominalc                    s(   i | ] \}}t |tƒr|ˆ v r||“qS r   )Ú
isinstancer   )r   ÚnameÚcat©Úcolumns_to_selectr   r   r   ²   s   þz%_liac_arff_parser.<locals>.<dictcomp>Ú
attributeszfetch_openml with as_frame=TrueÚdataF)ÚcolumnsÚcopyT)Údeepc                    s   g | ]}|ˆ v r|‘qS r   r   ©r   Úcolr7   r   r   Ú
<listcomp>Å   ó    z%_liac_arff_parser.<locals>.<listcomp>r   r   r   )Zignore_indexÚ	data_typeÚintegerÚInt64ÚnominalÚcategoryc                    s   g | ]}t ˆ | d  ƒ‘qS ©Úindex©Úint©r   Úcol_name©Úopenml_columns_infor   r   r@   ë   s   ÿc                    s   g | ]}t ˆ | d  ƒ‘qS rG   rI   rK   rM   r   r   r@   ï   s   ÿNz6shape must be provided when arr['data'] is a Generatoréÿÿÿÿr$   )r   Úcount)Úshaper   z-Unexpected type for data obtained from arff: c                    s   h | ]}|ˆ v ’qS r   r   rK   )Ú
categoriesr   r   Ú	<setcomp>  s   z$_liac_arff_parser.<locals>.<setcomp>c              
      sJ   g | ]B\}}t  t jˆ  |¡d d�ˆdd…||d …f jtdd�¡‘qS )ÚOr   Nr   F)r<   )r"   ZtakeZasarrayÚpopÚastyperJ   )r   ÚirL   )rR   r&   r   r   r@     s
   ü þzAMix of nominal and non-nominal targets is not currently supported)rO   )/r   ZCOOZ	DENSE_GENÚloadr
   r   r   ÚkeysÚnextZ	DataFrameZmemory_usageÚsumr	   r   r   r!   rV   ÚdtypesÚconcatr   r;   Úlowerr*   r4   r   Ú
ValueErrorr"   ZfromiterÚ	itertoolsÚchainÚfrom_iterableZreshapeÚtupler   r    Úspr0   Z
coo_matrixr$   Ztocsrr'   ÚtypeÚallZhstackr   ÚanyrQ   )"r-   Úoutput_arrays_typerN   Úfeature_names_to_selectÚtarget_names_to_selectrQ   r/   Ústreamr2   r3   Zarff_containerÚpdZcolumns_infoZcolumns_namesÚ	first_rowZfirst_dfZ	row_bytesÚ	chunksizeÚcolumns_to_keepÚdfsr:   r(   r\   r5   Úcolumn_dtyper)   r   Zfeature_indices_to_selectZtarget_indices_to_selectrP   Zarff_data_Xr%   ZX_shapeZis_classificationr   )rR   r8   rN   r&   r   Ú_liac_arff_parserk   sÊ    7
ÿ
þ

ÿ




ÿ
þ
þ
ÿ
ý

ýÿ
ÿ
ûÿ	
ÿ
rr   c              
      sØ  ddl ‰| D ]}| d¡ ¡  d¡r q*qi ‰|D ]:}|| d }| ¡ dkrXdˆ|< q2| ¡ dkr2d	ˆ|< q2‡fd
d„t|ƒD ƒ}	dddgddddd|	dœ	}
i |
¥|pªi ¥}ˆj| fi |¤Ž}zdd„ |D ƒ|_W n4 t�y } zˆj 	d¡|‚W Y d}~n
d}~0 0 || ‰ ‡ fdd„|jD ƒ}|| }t
 d¡‰‡fdd„}‡fdd„|j ¡ D ƒ}|D ]}|| j |¡||< �q`t|||ƒ\}}|dk�r¢|||dfS | ¡ | ¡  }}‡fdd„|j ¡ D ƒ}||d|fS )a^  ARFF parser using `pandas.read_csv`.

    This parser uses the metadata fetched directly from OpenML and skips the metadata
    headers of ARFF file itself. The data is loaded as a CSV file.

    Parameters
    ----------
    gzip_file : GzipFile instance
        The GZip compressed file with the ARFF formatted payload.

    output_arrays_type : {"numpy", "sparse", "pandas"}
        The type of the arrays that will be returned. The possibilities are:

        - `"numpy"`: both `X` and `y` will be NumPy arrays;
        - `"sparse"`: `X` will be sparse matrix and `y` will be a NumPy array;
        - `"pandas"`: `X` will be a pandas DataFrame and `y` will be either a
          pandas Series or DataFrame.

    openml_columns_info : dict
        The information provided by OpenML regarding the columns of the ARFF
        file.

    feature_names_to_select : list of str
        A list of the feature names to be selected to build `X`.

    target_names_to_select : list of str
        A list of the target names to be selected to build `y`.

    read_csv_kwargs : dict, default=None
        Keyword arguments to pass to `pandas.read_csv`. It allows to overwrite
        the default options.

    Returns
    -------
    X : {ndarray, sparse matrix, dataframe}
        The data matrix.

    y : {ndarray, dataframe, series}
        The target.

    frame : dataframe or None
        A dataframe containing both `X` and `y`. `None` if
        `output_array_type != "pandas"`.

    categories : list of str or None
        The names of the features that are categorical. `None` if
        `output_array_type == "pandas"`.
    r   Nr+   z@datarB   rC   rD   rE   rF   c                    s"   i | ]\}}|ˆ v r|ˆ | “qS r   r   )r   r   r5   )r\   r   r   r   �  s   þz'_pandas_arff_parser.<locals>.<dictcomp>Fú?ú%ú"Tú\)	ÚheaderZ	index_colZ	na_valuesZkeep_default_naÚcommentÚ	quotecharÚskipinitialspaceÚ
escapecharr   c                 S   s   g | ]}|‘qS r   r   )r   r5   r   r   r   r@   ™  rA   z'_pandas_arff_parser.<locals>.<listcomp>zwThe number of columns provided by OpenML does not match the number of columns inferred by pandas when reading the file.c                    s   g | ]}|ˆ v r|‘qS r   r   r>   r7   r   r   r@   ¡  rA   z^'(?P<contents>.*)'$c                    s"   t  ˆ | ¡}|d u r| S | d¡S )NÚcontents)ÚreÚsearchÚgroup)Zinput_stringÚmatch)Úsingle_quote_patternr   r   Ústrip_single_quotes±  s    z0_pandas_arff_parser.<locals>.strip_single_quotesc                    s    g | ]\}}t |ˆ jƒr|‘qS r   )r4   ÚCategoricalDtype©r   r5   r   ©rl   r   r   r@   ¸  s   þr1   c                    s(   i | ] \}}t |ˆ jƒr||j ¡ “qS r   )r4   rƒ   rR   Útolistr„   r…   r   r   r   Ç  s   þ)r1   r,   r^   Ú
startswithr   Zread_csvr;   r_   ÚerrorsZParserErrorr}   Úcompiler\   Úitemsr6   Zrename_categoriesr*   Zto_numpy)r-   rh   rN   ri   rj   Úread_csv_kwargsr.   r5   rq   Zdtypes_positionalZdefault_read_csv_kwargsr(   Úexcro   r‚   Zcategorical_columnsr?   r)   r&   rR   r   )r8   r\   rl   r�   r   Ú_pandas_arff_parser7  sh    8


þ÷ÿý

þ

þr�   c                 C   sH   |dkrt | |||||ƒS |dkr4t| |||||ƒS td|› d�ƒ‚dS )a6  Load a compressed ARFF file using a given parser.

    Parameters
    ----------
    gzip_file : GzipFile instance
        The file compressed to be read.

    parser : {"pandas", "liac-arff"}
        The parser used to parse the ARFF file. "pandas" is recommended
        but only supports loading dense datasets.

    output_type : {"numpy", "sparse", "pandas"}
        The type of the arrays that will be returned. The possibilities ara:

        - `"numpy"`: both `X` and `y` will be NumPy arrays;
        - `"sparse"`: `X` will be sparse matrix and `y` will be a NumPy array;
        - `"pandas"`: `X` will be a pandas DataFrame and `y` will be either a
          pandas Series or DataFrame.

    openml_columns_info : dict
        The information provided by OpenML regarding the columns of the ARFF
        file.

    feature_names_to_select : list of str
        A list of the feature names to be selected.

    target_names_to_select : list of str
        A list of the target names to be selected.

    read_csv_kwargs : dict, default=None
        Keyword arguments to pass to `pandas.read_csv`. It allows to overwrite
        the default options.

    Returns
    -------
    X : {ndarray, sparse matrix, dataframe}
        The data matrix.

    y : {ndarray, dataframe, series}
        The target.

    frame : dataframe or None
        A dataframe containing both `X` and `y`. `None` if
        `output_array_type != "pandas"`.

    categories : list of str or None
        The names of the features that are categorical. `None` if
        `output_array_type == "pandas"`.
    z	liac-arffr1   zUnknown parser: 'z%'. Should be 'liac-arff' or 'pandas'.N)rr   r�   r_   )r-   ÚparserÚoutput_typerN   ri   rj   rQ   r‹   r   r   r   Úload_arff_from_gzip_fileÏ  s*    ;úú	
ÿr�   )N)N)NN)Ú__doc__r`   r}   Úcollectionsr   Úcollections.abcr   Útypingr   Únumpyr"   Zscipyrd   Z	externalsr   Zexternals._arffr   Zutils._chunkingr   r	   Zutils._optional_dependenciesr
   Zutils.fixesr   r   Zndarrayr'   r*   rr   r�   r�   r   r   r   r   Ú<module>   s8   þ$þ& ú
 S ú
    ø