U
    Cvf                     @  s  d dl mZ d dlZd dlZd dlmZ d dlmZmZm	Z	m
Z
mZ d dlZd dlmZ d dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZ erd dlmZmZmZ dd Zdd Zdd Z dd Z!dd Z"dd Z#dddej$ddfdddd d!d"Z%ej$ddfdddd d#d$Z&dddej$ddfdddd d%d&Z'd'd( Z(ej$ddfddd)d*d+Z)eeed, f Z*dddej$ddfd,d-d.d.d.d/ddd0d1	d2d3Z+d4d5 Z,ej$dddddfdddd d6d7Z-g dddej$dddfd8dd9d.d/ddd:d;d<	d=d>Z.dS )?    )annotationsN)Counter)TYPE_CHECKINGIterableLiteralSequenceUnion)dtypes)concat)	DataArray)Dataset)merge)iterate_nested)CombineAttrsOptionsCompatOptionsJoinOptionsc                 C  s   t t| dS )N )dict _infer_tile_ids_from_nested_list)datasetsr   r   7/tmp/pip-unpacked-wheel-h316xyqg/xarray/core/combine.py"_infer_concat_order_from_positions   s    r   c                 c  sB   t | tr4t| D ]\}}t|||f E dH  qn
|| fV  dS )a  
    Given a list of lists (of lists...) of objects, returns a iterator
    which returns a tuple containing the index of each object in the nested
    list structure as the key, and the object. This can then be called by the
    dict constructor to create a dictionary of the objects organised by their
    position in the original nested list.

    Recursively traverses the given structure, while keeping track of the
    current position. Should work for any type of object which isn't a list.

    Parameters
    ----------
    entry : list[list[obj, obj, ...], ...]
        List of lists of arbitrary depth, containing objects in the order
        they are to be concatenated.

    Returns
    -------
    combined_tile_ids : dict[tuple(int, ...), obj]
    N)
isinstancelist	enumerater   )entryZcurrent_posiitemr   r   r   r      s    
r   c                   s   | j tkrt| t}t|dkrz"dd l t fdd|D }W n tk
r^   d}Y nX d	dd |D }d| d	| d
}|r| d}t
|d S )N   r   c                 3  s   | ]}t | jV  qd S N)
issubclassdatetime.0tcftimer   r   	<genexpr>>   s     z%_ensure_same_types.<locals>.<genexpr>Fz, c                 s  s   | ]}|j V  qd S r   )__name__r"   r   r   r   r'   B   s     z Cannot combine along dimension 'z' with mixed types. Found: .zZ If importing data directly from a file then setting `use_cftime=True` may fix this issue.)Zdtypeobjectsetmaptypelenr&   anyImportErrorjoin	TypeError)seriesdimtypesZcftimes	error_msgr   r%   r   _ensure_same_types6   s    

r7   c           
        sv  g }dd | D }| d }|j D ]   |kr  fdd| D tdd D rZtddd D tfd	dd
d  D s |  tdd D rd}n&tdd D rd}ntd tdd D rtdtdd D }| }t	|  |j
d|dd}|tjd
 }dd t||D }q t| d
kr`|s`tdtt|| }	|	|fS )Nc                 S  s   g | ]}d qS )r   r   r#   dsr   r   r   
<listcomp>T   s     z3_infer_concat_order_from_coords.<locals>.<listcomp>r   c                   s   g | ]}|j  qS r   )Z_indexesgetr8   r4   r   r   r:   ^   s     c                 s  s   | ]}|d kV  qd S r   r   r#   indexr   r   r   r'   _   s     z2_infer_concat_order_from_coords.<locals>.<genexpr>zDEvery dimension needs a coordinate for inferring concatenation orderc                 S  s   g | ]}|  qS r   )Zto_pandas_indexr=   r   r   r   r:   f   s     c                 3  s   | ]}|  d  V  qdS r   N)equalsr=   )indexesr   r   r'   j   s     r   c                 s  s   | ]}|j V  qd S r   )is_monotonic_increasingr=   r   r   r   r'   o   s     Tc                 s  s   | ]}|j V  qd S r   )is_monotonic_decreasingr=   r   r   r   r'   q   s     FzgCoordinate variable {} is neither monotonically increasing nor monotonically decreasing on all datasetsc                 s  s   | ]}|j d kV  qdS r?   )sizer=   r   r   r   r'   |   s     z"Cannot handle size zero dimensionsc                 S  s   g | ]}|d  qS )r   r   r=   r   r   r   r:   ~   s     Zdense)method	ascendingZnumeric_onlyc                 S  s   g | ]\}}||f qS r   r   )r#   tile_idpositionr   r   r   r:      s    zWCould not find any dimension coordinates to use to order the datasets for concatenation)Zdimsr/   
ValueErrorallappendformatpdZIndexZ	to_seriesr7   rankZastypeintvalueszipr.   r   )
r   concat_dimstile_idsZds0rF   Zfirst_itemsr3   rN   ordercombined_idsr   )r4   rA   r   _infer_concat_order_from_coordsQ   sT    

  rV   c                 C  sB   |   }dd |D }|s dg}t||d hkr:td||fS )zk
    Check all tuples are the same length, i.e. check that all lists are
    nested to the same depth.
    c                 S  s   g | ]}t |qS r   )r.   r#   rG   r   r   r   r:      s     z3_check_dimension_depth_tile_ids.<locals>.<listcomp>r   z\The supplied objects do not form a hypercube because sub-lists do not have consistent depths)keysr+   rI   )combined_tile_idsrS   nesting_depthsr   r   r   _check_dimension_depth_tile_ids   s    r[   c                   s`   t | \}}t|d D ]B  fdd|D }t|}tt| dkrtdt  qdS )z4Check all lists along one dimension are same length.r   c                   s   g | ]}|  qS r   r   rW   r<   r   r   r:      s     z)_check_shape_tile_ids.<locals>.<listcomp>r   zmThe supplied objects do not form a hypercube because sub-lists do not have consistent lengths along dimensionN)r[   ranger   r.   r+   rP   rI   str)rY   rS   rZ   Zindices_along_dimoccurrencesr   r<   r   _check_shape_tile_ids   s    r_   rJ   Z	differentZno_conflictsouterZdropr   r   r   )compatr1   combine_attrsc                 C  sh   t t|  }t|}	t||	kr8tdt||	|D ]}
t| |
||||||d} q<|  \}|S )a  
    Combines an N-dimensional structure of datasets into one by applying a
    series of either concat and merge operations along each dimension.

    No checks are performed on the consistency of the datasets, concat_dims or
    tile_IDs, because it is assumed that this has already been done.

    Parameters
    ----------
    combined_ids : Dict[Tuple[int, ...]], xarray.Dataset]
        Structure containing all datasets to be concatenated with "tile_IDs" as
        keys, which specify position within the desired final combined result.
    concat_dims : sequence of str
        The dimensions along which the datasets should be concatenated. Must be
        in order, and the length must match the length of the tuples used as
        keys in combined_ids. If the string is a dimension name then concat
        along that dimension, if it is None then merge.

    Returns
    -------
    combined_ds : xarray.Dataset
    zZconcat_dims has length {} but the datasets passed are nested in a {}-dimensional structurer4   	data_varscoordsra   
fill_valuer1   rb   )nextiterrX   r.   rI   rL   _combine_all_along_first_dimrP   )rU   rR   rd   re   ra   rf   r1   rb   Zexample_tile_idZn_dims
concat_dimZcombined_dsr   r   r   _combine_nd   s,    ! 


rk   c              
   C  sj   t t|  td} tj|  td}i }	|D ]6\}
}t t|} |  }t|||||||||	|
< q.|	S )Nkey)r   sorteditems_new_tile_id	itertoolsgroupbyrP   _combine_1d)rU   r4   rd   re   ra   rf   r1   rb   ZgroupedZnew_combined_idsZnew_idgroupr   r   r   r   ri      s"           
ri   c           
   
   C  sx   |dk	rbzt | |||||||d}W qt tk
r^ }	 zdt|	krLtdn W 5 d}	~	X Y qtX nt| ||||d}|S )zd
    Applies either concat or merge to 1D list of datasets depending on value
    of concat_dim
    Nrc   zencountered unexpected variablezThese objects cannot be combined using only xarray.combine_nested, instead either use xarray.combine_by_coords, or do it manually with xarray.concat, xarray.merge and xarray.alignra   rf   r1   rb   )r
   rI   r]   r   )
r   rj   ra   rd   re   rf   r1   rb   combinederrr   r   r   rs     s4    

rs   c                 C  s   | \}}|dd  S )Nr   r   )Zsingle_id_ds_pairrG   r9   r   r   r   rp   K  s    rp   )r1   rb   c	              
   C  sR   t | dkrt S |s t| }	ntt|| }	t|	 t|	|||||||d}
|
S )Nr   )ra   rd   re   rf   r1   rb   )r.   r   r   r   rQ   r_   rk   )r   rR   ra   rd   re   idsrf   r1   rb   rU   rv   r   r   r   _nested_combineP  s"    

ry   DATASET_HYPERCUBEzDstr | DataArray | None | Sequence[str | DataArray | pd.Index | None]r]   r*   r   )	r   rj   ra   rd   re   rf   r1   rb   returnc           	      C  sn   t dd t| D o*t dd t| D }|r8tdt|ttfsN|dkrT|g}t| ||||d|||d	S )a  
    Explicitly combine an N-dimensional grid of datasets into one by using a
    succession of concat and merge operations along each dimension of the grid.

    Does not sort the supplied datasets under any circumstances, so the
    datasets must be passed in the order you wish them to be concatenated. It
    does align coordinates, but different variables on datasets can cause it to
    fail under some scenarios. In complex cases, you may need to clean up your
    data and use concat/merge explicitly.

    To concatenate along multiple dimensions the datasets must be passed as a
    nested list-of-lists, with a depth equal to the length of ``concat_dims``.
    ``combine_nested`` will concatenate along the top-level list first.

    Useful for combining datasets from a set of nested directories, or for
    collecting the output of a simulation parallelized along multiple
    dimensions.

    Parameters
    ----------
    datasets : list or nested list of Dataset
        Dataset objects to combine.
        If concatenation or merging along more than one dimension is desired,
        then datasets must be supplied in a nested list-of-lists.
    concat_dim : str, or list of str, DataArray, Index or None
        Dimensions along which to concatenate variables, as used by
        :py:func:`xarray.concat`.
        Set ``concat_dim=[..., None, ...]`` explicitly to disable concatenation
        and merge instead along a particular dimension.
        The position of ``None`` in the list specifies the dimension of the
        nested-list input along which to merge.
        Must be the same length as the depth of the list passed to
        ``datasets``.
    compat : {"identical", "equals", "broadcast_equals",               "no_conflicts", "override"}, optional
        String indicating how to compare variables of the same name for
        potential merge conflicts:

        - "broadcast_equals": all values must be equal when variables are
          broadcast against each other to ensure common dimensions.
        - "equals": all values and dimensions must be the same.
        - "identical": all values, dimensions and attributes must be the
          same.
        - "no_conflicts": only values which are not null in both datasets
          must be equal. The returned dataset then contains the combination
          of all non-null values.
        - "override": skip comparing and pick variable from first dataset
    data_vars : {"minimal", "different", "all" or list of str}, optional
        Details are in the documentation of concat
    coords : {"minimal", "different", "all" or list of str}, optional
        Details are in the documentation of concat
    fill_value : scalar or dict-like, optional
        Value to use for newly missing values. If a dict-like, maps
        variable names to fill values. Use a data array's name to
        refer to its values.
    join : {"outer", "inner", "left", "right", "exact"}, optional
        String indicating how to combine differing indexes
        (excluding concat_dim) in objects

        - "outer": use the union of object indexes
        - "inner": use the intersection of object indexes
        - "left": use indexes from the first object with each dimension
        - "right": use indexes from the last object with each dimension
        - "exact": instead of aligning, raise `ValueError` when indexes to be
          aligned are not equal
        - "override": if indexes are of same size, rewrite indexes to be
          those of the first object with that dimension. Indexes for the same
          dimension must have the same size in all objects.
    combine_attrs : {"drop", "identical", "no_conflicts", "drop_conflicts",                      "override"} or callable, default: "drop"
        A callable or a string indicating how to combine attrs of the objects being
        merged:

        - "drop": empty attrs on returned Dataset.
        - "identical": all attrs must be the same on every object.
        - "no_conflicts": attrs from all objects are combined, any that have
          the same name must also have the same value.
        - "drop_conflicts": attrs from all objects are combined, any that have
          the same name but different values are dropped.
        - "override": skip comparing and copy attrs from the first dataset to
          the result.

        If a callable, it must expect a sequence of ``attrs`` dicts and a context object
        as its only parameters.

    Returns
    -------
    combined : xarray.Dataset

    Examples
    --------

    A common task is collecting data from a parallelized simulation in which
    each process wrote out to a separate file. A domain which was decomposed
    into 4 parts, 2 each along both the x and y axes, requires organising the
    datasets into a doubly-nested list, e.g:

    >>> x1y1 = xr.Dataset(
    ...     {
    ...         "temperature": (("x", "y"), np.random.randn(2, 2)),
    ...         "precipitation": (("x", "y"), np.random.randn(2, 2)),
    ...     }
    ... )
    >>> x1y1
    <xarray.Dataset>
    Dimensions:        (x: 2, y: 2)
    Dimensions without coordinates: x, y
    Data variables:
        temperature    (x, y) float64 1.764 0.4002 0.9787 2.241
        precipitation  (x, y) float64 1.868 -0.9773 0.9501 -0.1514
    >>> x1y2 = xr.Dataset(
    ...     {
    ...         "temperature": (("x", "y"), np.random.randn(2, 2)),
    ...         "precipitation": (("x", "y"), np.random.randn(2, 2)),
    ...     }
    ... )
    >>> x2y1 = xr.Dataset(
    ...     {
    ...         "temperature": (("x", "y"), np.random.randn(2, 2)),
    ...         "precipitation": (("x", "y"), np.random.randn(2, 2)),
    ...     }
    ... )
    >>> x2y2 = xr.Dataset(
    ...     {
    ...         "temperature": (("x", "y"), np.random.randn(2, 2)),
    ...         "precipitation": (("x", "y"), np.random.randn(2, 2)),
    ...     }
    ... )


    >>> ds_grid = [[x1y1, x1y2], [x2y1, x2y2]]
    >>> combined = xr.combine_nested(ds_grid, concat_dim=["x", "y"])
    >>> combined
    <xarray.Dataset>
    Dimensions:        (x: 4, y: 4)
    Dimensions without coordinates: x, y
    Data variables:
        temperature    (x, y) float64 1.764 0.4002 -0.1032 ... 0.04576 -0.1872
        precipitation  (x, y) float64 1.868 -0.9773 0.761 ... -0.7422 0.1549 0.3782

    ``combine_nested`` can also be used to explicitly merge datasets with
    different variables. For example if we have 4 datasets, which are divided
    along two times, and contain two different variables, we can pass ``None``
    to ``concat_dim`` to specify the dimension of the nested list over which
    we wish to use ``merge`` instead of ``concat``:

    >>> t1temp = xr.Dataset({"temperature": ("t", np.random.randn(5))})
    >>> t1temp
    <xarray.Dataset>
    Dimensions:      (t: 5)
    Dimensions without coordinates: t
    Data variables:
        temperature  (t) float64 -0.8878 -1.981 -0.3479 0.1563 1.23

    >>> t1precip = xr.Dataset({"precipitation": ("t", np.random.randn(5))})
    >>> t1precip
    <xarray.Dataset>
    Dimensions:        (t: 5)
    Dimensions without coordinates: t
    Data variables:
        precipitation  (t) float64 1.202 -0.3873 -0.3023 -1.049 -1.42

    >>> t2temp = xr.Dataset({"temperature": ("t", np.random.randn(5))})
    >>> t2precip = xr.Dataset({"precipitation": ("t", np.random.randn(5))})


    >>> ds_grid = [[t1temp, t1precip], [t2temp, t2precip]]
    >>> combined = xr.combine_nested(ds_grid, concat_dim=["t", None])
    >>> combined
    <xarray.Dataset>
    Dimensions:        (t: 10)
    Dimensions without coordinates: t
    Data variables:
        temperature    (t) float64 -0.8878 -1.981 -0.3479 ... -0.5097 -0.4381 -1.253
        precipitation  (t) float64 1.202 -0.3873 -0.3023 ... -0.2127 -0.8955 0.3869

    See also
    --------
    concat
    merge
    c                 s  s   | ]}t |tV  qd S r   )r   r   r#   objr   r   r   r'   >  s    z!combine_nested.<locals>.<genexpr>c                 s  s"   | ]}t |to|jd kV  qd S r   r   r   namer|   r   r   r   r'   @  s   z+Can't combine datasets with unnamed arrays.NF)rR   ra   rd   re   rx   rf   r1   rb   )r/   r   rI   r   r]   r   ry   )	r   rj   ra   rd   re   rf   r1   rb   Zmixed_datasets_and_arraysr   r   r   combine_nested  s.     @r   c                 C  s   t t| S r   )tuplern   )r9   r   r   r   vars_as_keysX  s    r   c              
   C  s   t | dkrtdtt| \}}|dkr6t| nt| t||||||||d}	|D ]*}
|	j|
}|j	sZ|j
sZtd|
qZ|	S )af  
    Attempt to combine a list of Datasets into a hypercube using their
    coordinates.

    All provided Datasets must belong to a single variable, ie. must be
    assigned the same variable name. This precondition is not checked by this
    function, so the caller is assumed to know what it's doing.

    This function is NOT part of the public API.
    r   zRAt least one Dataset is required to resolve variable names for combined hypercube.N)rR   rd   re   ra   rf   r1   rb   zJResulting object does not have monotonic global indexes along dimension {})r.   rI   rV   r   r_   r[   rk   rA   r;   rB   rC   rL   )r   rf   rd   re   ra   r1   rb   rU   rR   concatenatedr4   rA   r   r   r   "_combine_single_variable_hypercube\  s6    
r   zIterable[Dataset | DataArray]z4Literal[('all', 'minimal', 'different')] | list[str]zIterable[Dataset] | NonezDataset | DataArray)	data_objectsra   rd   re   rf   r1   rb   r   r{   c              
   C  s   |dk	rt d |} | s t S dd | D }t|rxt|rndd | D }	t|	||||||d}
t |
S tdn^dd | D } t	| t
d	}tj|t
d	}g }|D ],\}}tt|||||||d}|| qt|||||d
S )a/)  

    Attempt to auto-magically combine the given datasets (or data arrays)
    into one by using dimension coordinates.

    This function attempts to combine a group of datasets along any number of
    dimensions into a single entity by inspecting coords and metadata and using
    a combination of concat and merge.

    Will attempt to order the datasets such that the values in their dimension
    coordinates are monotonic along all dimensions. If it cannot determine the
    order in which to concatenate the datasets, it will raise a ValueError.
    Non-coordinate dimensions will be ignored, as will any coordinate
    dimensions which do not vary between each dataset.

    Aligns coordinates, but different variables on datasets can cause it
    to fail under some scenarios. In complex cases, you may need to clean up
    your data and use concat/merge explicitly (also see `combine_nested`).

    Works well if, for example, you have N years of data and M data variables,
    and each combination of a distinct time period and set of data variables is
    saved as its own dataset. Also useful for if you have a simulation which is
    parallelized in multiple dimensions, but has global coordinates saved in
    each file specifying the positions of points within the global domain.

    Parameters
    ----------
    data_objects : Iterable of Datasets or DataArrays
        Data objects to combine.

    compat : {"identical", "equals", "broadcast_equals", "no_conflicts", "override"}, optional
        String indicating how to compare variables of the same name for
        potential conflicts:

        - "broadcast_equals": all values must be equal when variables are
          broadcast against each other to ensure common dimensions.
        - "equals": all values and dimensions must be the same.
        - "identical": all values, dimensions and attributes must be the
          same.
        - "no_conflicts": only values which are not null in both datasets
          must be equal. The returned dataset then contains the combination
          of all non-null values.
        - "override": skip comparing and pick variable from first dataset

    data_vars : {"minimal", "different", "all" or list of str}, optional
        These data variables will be concatenated together:

        - "minimal": Only data variables in which the dimension already
          appears are included.
        - "different": Data variables which are not equal (ignoring
          attributes) across all datasets are also concatenated (as well as
          all for which dimension already appears). Beware: this option may
          load the data payload of data variables into memory if they are not
          already loaded.
        - "all": All data variables will be concatenated.
        - list of str: The listed data variables will be concatenated, in
          addition to the "minimal" data variables.

        If objects are DataArrays, `data_vars` must be "all".
    coords : {"minimal", "different", "all"} or list of str, optional
        As per the "data_vars" kwarg, but for coordinate variables.
    fill_value : scalar or dict-like, optional
        Value to use for newly missing values. If a dict-like, maps
        variable names to fill values. Use a data array's name to
        refer to its values. If None, raises a ValueError if
        the passed Datasets do not create a complete hypercube.
    join : {"outer", "inner", "left", "right", "exact"}, optional
        String indicating how to combine differing indexes in objects

        - "outer": use the union of object indexes
        - "inner": use the intersection of object indexes
        - "left": use indexes from the first object with each dimension
        - "right": use indexes from the last object with each dimension
        - "exact": instead of aligning, raise `ValueError` when indexes to be
          aligned are not equal
        - "override": if indexes are of same size, rewrite indexes to be
          those of the first object with that dimension. Indexes for the same
          dimension must have the same size in all objects.

    combine_attrs : {"drop", "identical", "no_conflicts", "drop_conflicts",                      "override"} or callable, default: "drop"
        A callable or a string indicating how to combine attrs of the objects being
        merged:

        - "drop": empty attrs on returned Dataset.
        - "identical": all attrs must be the same on every object.
        - "no_conflicts": attrs from all objects are combined, any that have
          the same name must also have the same value.
        - "drop_conflicts": attrs from all objects are combined, any that have
          the same name but different values are dropped.
        - "override": skip comparing and copy attrs from the first dataset to
          the result.

        If a callable, it must expect a sequence of ``attrs`` dicts and a context object
        as its only parameters.

    datasets : Iterable of Datasets

    Returns
    -------
    combined : xarray.Dataset or xarray.DataArray
        Will return a Dataset unless all the inputs are unnamed DataArrays, in which case a
        DataArray will be returned.

    See also
    --------
    concat
    merge
    combine_nested

    Examples
    --------

    Combining two datasets using their common dimension coordinates. Notice
    they are concatenated based on the values in their dimension coordinates,
    not on their position in the list passed to `combine_by_coords`.

    >>> x1 = xr.Dataset(
    ...     {
    ...         "temperature": (("y", "x"), 20 * np.random.rand(6).reshape(2, 3)),
    ...         "precipitation": (("y", "x"), np.random.rand(6).reshape(2, 3)),
    ...     },
    ...     coords={"y": [0, 1], "x": [10, 20, 30]},
    ... )
    >>> x2 = xr.Dataset(
    ...     {
    ...         "temperature": (("y", "x"), 20 * np.random.rand(6).reshape(2, 3)),
    ...         "precipitation": (("y", "x"), np.random.rand(6).reshape(2, 3)),
    ...     },
    ...     coords={"y": [2, 3], "x": [10, 20, 30]},
    ... )
    >>> x3 = xr.Dataset(
    ...     {
    ...         "temperature": (("y", "x"), 20 * np.random.rand(6).reshape(2, 3)),
    ...         "precipitation": (("y", "x"), np.random.rand(6).reshape(2, 3)),
    ...     },
    ...     coords={"y": [2, 3], "x": [40, 50, 60]},
    ... )

    >>> x1
    <xarray.Dataset>
    Dimensions:        (y: 2, x: 3)
    Coordinates:
      * y              (y) int64 0 1
      * x              (x) int64 10 20 30
    Data variables:
        temperature    (y, x) float64 10.98 14.3 12.06 10.9 8.473 12.92
        precipitation  (y, x) float64 0.4376 0.8918 0.9637 0.3834 0.7917 0.5289

    >>> x2
    <xarray.Dataset>
    Dimensions:        (y: 2, x: 3)
    Coordinates:
      * y              (y) int64 2 3
      * x              (x) int64 10 20 30
    Data variables:
        temperature    (y, x) float64 11.36 18.51 1.421 1.743 0.4044 16.65
        precipitation  (y, x) float64 0.7782 0.87 0.9786 0.7992 0.4615 0.7805

    >>> x3
    <xarray.Dataset>
    Dimensions:        (y: 2, x: 3)
    Coordinates:
      * y              (y) int64 2 3
      * x              (x) int64 40 50 60
    Data variables:
        temperature    (y, x) float64 2.365 12.8 2.867 18.89 10.44 8.293
        precipitation  (y, x) float64 0.2646 0.7742 0.4562 0.5684 0.01879 0.6176

    >>> xr.combine_by_coords([x2, x1])
    <xarray.Dataset>
    Dimensions:        (y: 4, x: 3)
    Coordinates:
      * y              (y) int64 0 1 2 3
      * x              (x) int64 10 20 30
    Data variables:
        temperature    (y, x) float64 10.98 14.3 12.06 10.9 ... 1.743 0.4044 16.65
        precipitation  (y, x) float64 0.4376 0.8918 0.9637 ... 0.7992 0.4615 0.7805

    >>> xr.combine_by_coords([x3, x1])
    <xarray.Dataset>
    Dimensions:        (y: 4, x: 6)
    Coordinates:
      * y              (y) int64 0 1 2 3
      * x              (x) int64 10 20 30 40 50 60
    Data variables:
        temperature    (y, x) float64 10.98 14.3 12.06 nan ... nan 18.89 10.44 8.293
        precipitation  (y, x) float64 0.4376 0.8918 0.9637 ... 0.5684 0.01879 0.6176

    >>> xr.combine_by_coords([x3, x1], join="override")
    <xarray.Dataset>
    Dimensions:        (y: 2, x: 6)
    Coordinates:
      * y              (y) int64 0 1
      * x              (x) int64 10 20 30 40 50 60
    Data variables:
        temperature    (y, x) float64 10.98 14.3 12.06 2.365 ... 18.89 10.44 8.293
        precipitation  (y, x) float64 0.4376 0.8918 0.9637 ... 0.5684 0.01879 0.6176

    >>> xr.combine_by_coords([x1, x2, x3])
    <xarray.Dataset>
    Dimensions:        (y: 4, x: 6)
    Coordinates:
      * y              (y) int64 0 1 2 3
      * x              (x) int64 10 20 30 40 50 60
    Data variables:
        temperature    (y, x) float64 10.98 14.3 12.06 nan ... 18.89 10.44 8.293
        precipitation  (y, x) float64 0.4376 0.8918 0.9637 ... 0.5684 0.01879 0.6176

    You can also combine DataArray objects, but the behaviour will differ depending on
    whether or not the DataArrays are named. If all DataArrays are named then they will
    be promoted to Datasets before combining, and then the resultant Dataset will be
    returned, e.g.

    >>> named_da1 = xr.DataArray(
    ...     name="a", data=[1.0, 2.0], coords={"x": [0, 1]}, dims="x"
    ... )
    >>> named_da1
    <xarray.DataArray 'a' (x: 2)>
    array([1., 2.])
    Coordinates:
      * x        (x) int64 0 1

    >>> named_da2 = xr.DataArray(
    ...     name="a", data=[3.0, 4.0], coords={"x": [2, 3]}, dims="x"
    ... )
    >>> named_da2
    <xarray.DataArray 'a' (x: 2)>
    array([3., 4.])
    Coordinates:
      * x        (x) int64 2 3

    >>> xr.combine_by_coords([named_da1, named_da2])
    <xarray.Dataset>
    Dimensions:  (x: 4)
    Coordinates:
      * x        (x) int64 0 1 2 3
    Data variables:
        a        (x) float64 1.0 2.0 3.0 4.0

    If all the DataArrays are unnamed, a single DataArray will be returned, e.g.

    >>> unnamed_da1 = xr.DataArray(data=[1.0, 2.0], coords={"x": [0, 1]}, dims="x")
    >>> unnamed_da2 = xr.DataArray(data=[3.0, 4.0], coords={"x": [2, 3]}, dims="x")
    >>> xr.combine_by_coords([unnamed_da1, unnamed_da2])
    <xarray.DataArray (x: 4)>
    array([1., 2., 3., 4.])
    Coordinates:
      * x        (x) int64 0 1 2 3

    Finally, if you attempt to combine a mix of unnamed DataArrays with either named
    DataArrays or Datasets, a ValueError will be raised (as this is an ambiguous operation).
    NzxThe datasets argument has been renamed to `data_objects`. From 0.21 on passing a value for datasets will raise an error.c                 S  s    g | ]}t |to|jd kqS r   r~   )r#   Zdata_objectr   r   r   r:     s   z%combine_by_coords.<locals>.<listcomp>c                 S  s   g | ]}|  qS r   )Z_to_temp_dataset)r#   Zunnamed_dataarrayr   r   r   r:     s   )rf   rd   re   ra   r1   rb   zXCan't automatically combine unnamed DataArrays with either named DataArrays or Datasets.c                 S  s"   g | ]}t |tr| n|qS r   )r   r   Z
to_datasetr|   r   r   r   r:     s   rl   ru   )warningswarnr   r/   rJ   r   r   Z_from_temp_datasetrI   rn   r   rq   rr   r   rK   r   )r   ra   rd   re   rf   r1   rb   r   Zobjs_are_unnamed_dataarraysZtemp_datasetsZcombined_temp_datasetZsorted_datasetsZgrouped_by_varsZ!concatenated_grouped_by_data_varsvarsZdatasets_with_same_varsr   r   r   r   combine_by_coords  sl      		r   )/
__future__r   rq   r   collectionsr   typingr   r   r   r   r   ZpandasrM   Zxarray.corer	   Zxarray.core.concatr
   Zxarray.core.dataarrayr   Zxarray.core.datasetr   Zxarray.core.merger   Zxarray.core.utilsr   Zxarray.core.typesr   r   r   r   r   r7   rV   r[   r_   ZNArk   ri   rs   rp   ry   rz   r   r   r   r   r   r   r   r   <module>   s   ND2,  Z=