Instruction:
Implement a function in Python 3 to
set and control tick behavior on x and y axes.

Response:
def set_ticks(self, max_xticks=_NTICKS, max_yticks=_NTICKS,
                  fontsize=_FONTSIZE):
        """
        Set and control tick behavior

        Parameters
        ----------
        max_xticks, max_yticks : int, optional
            Maximum number of labeled ticks to plot on x, y axes
        fontsize : string or int
            Font size as used by matplotlib text

        Returns
        -------
        self : FacetGrid object

        """
        from matplotlib.ticker import MaxNLocator

        # Both are necessary
        x_major_locator = MaxNLocator(nbins=max_xticks)
        y_major_locator = MaxNLocator(nbins=max_yticks)

        for ax in self.axes.flat:
            ax.xaxis.set_major_locator(x_major_locator)
            ax.yaxis.set_major_locator(y_major_locator)
            for tick in itertools.chain(ax.xaxis.get_major_ticks(),
                                        ax.yaxis.get_major_ticks()):
                tick.label.set_fontsize(fontsize)

        return self


Instruction:
Explain what the following Python 3 code does
def map(self, func, *args, **kwargs):
        plt = import_matplotlib_pyplot()

        for ax, namedict in zip(self.axes.flat, self.name_dicts.flat):
            if namedict is not None:
                data = self.data.loc[namedict]
                plt.sca(ax)
                innerargs = [data[a].values for a in args]
                maybe_mappable = func(*innerargs, **kwargs)
                # TODO: better way to verify that an artist is mappable?
                # https://stackoverflow.com/questions/33023036/is-it-possible-to-detect-if-a-matplotlib-artist-is-a-mappable-suitable-for-use-w#33023522
                if (maybe_mappable and
                   hasattr(maybe_mappable, 'autoscale_None')):
                    self._mappables.append(maybe_mappable)

        self._finalize_grid(*args[:2])

        return self

Response: Applies a function to each facet s subset of the data.


Instruction:
Here you have a function in Python 3, explain what it does
def _get_time_bins(index, freq, closed, label, base):

    if not isinstance(index, CFTimeIndex):
        raise TypeError('index must be a CFTimeIndex, but got '
                        'an instance of %r' % type(index).__name__)
    if len(index) == 0:
        datetime_bins = labels = CFTimeIndex(data=[], name=index.name)
        return datetime_bins, labels

    first, last = _get_range_edges(index.min(), index.max(), freq,
                                   closed=closed,
                                   base=base)
    datetime_bins = labels = cftime_range(freq=freq,
                                          start=first,
                                          end=last,
                                          name=index.name)

    datetime_bins, labels = _adjust_bin_edges(datetime_bins, freq, closed,
                                              index, labels)

    if label == 'right':
        labels = labels[1:]
    else:
        labels = labels[:-1]

    # TODO: when CFTimeIndex supports missing values, if the reference index
    # contains missing values, insert the appropriate NaN value at the
    # beginning of the datetime_bins and labels indexes.

    return datetime_bins, labels

Response: Returns the bin labels and the corresponding datetime_bins for resampling operations.


Instruction:
Can you create a Python 3 function that
adjusts the bin edges of a single time series to match the given bin frequencies.

Response:
def _adjust_bin_edges(datetime_bins, offset, closed, index, labels):
    """This is required for determining the bin edges resampling with
    daily frequencies greater than one day, month end, and year end
    frequencies.

    Consider the following example.  Let's say you want to downsample the
    time series with the following coordinates to month end frequency:

    CFTimeIndex([2000-01-01 12:00:00, 2000-01-31 12:00:00,
                 2000-02-01 12:00:00], dtype='object')

    Without this adjustment, _get_time_bins with month-end frequency will
    return the following index for the bin edges (default closed='right' and
    label='right' in this case):

    CFTimeIndex([1999-12-31 00:00:00, 2000-01-31 00:00:00,
                 2000-02-29 00:00:00], dtype='object')

    If 2000-01-31 is used as a bound for a bin, the value on
    2000-01-31T12:00:00 (at noon on January 31st), will not be included in the
    month of January.  To account for this, pandas adds a day minus one worth
    of microseconds to the bin edges generated by cftime range, so that we do
    bin the value at noon on January 31st in the January bin.  This results in
    an index with bin edges like the following:

    CFTimeIndex([1999-12-31 23:59:59, 2000-01-31 23:59:59,
                 2000-02-29 23:59:59], dtype='object')

    The labels are still:

    CFTimeIndex([2000-01-31 00:00:00, 2000-02-29 00:00:00], dtype='object')

    This is also required for daily frequencies longer than one day and
    year-end frequencies.
    """
    is_super_daily = (isinstance(offset, (MonthEnd, QuarterEnd, YearEnd)) or
                      (isinstance(offset, Day) and offset.n > 1))
    if is_super_daily:
        if closed == 'right':
            datetime_bins = datetime_bins + datetime.timedelta(days=1,
                                                               microseconds=-1)
        if datetime_bins[-2] > index.max():
            datetime_bins = datetime_bins[:-1]
            labels = labels[:-1]

    return datetime_bins, labels


Instruction:
How would you implement a function in Python 3 that
gets the correct starting and ending datetimes for the resampled CFTimeIndex range.

Response:
def _get_range_edges(first, last, offset, closed='left', base=0):
    """ Get the correct starting and ending datetimes for the resampled
    CFTimeIndex range.

    Parameters
    ----------
    first : cftime.datetime
        Uncorrected starting datetime object for resampled CFTimeIndex range.
        Usually the min of the original CFTimeIndex.
    last : cftime.datetime
        Uncorrected ending datetime object for resampled CFTimeIndex range.
        Usually the max of the original CFTimeIndex.
    offset : xarray.coding.cftime_offsets.BaseCFTimeOffset
        The offset object representing target conversion a.k.a. resampling
        frequency. Contains information on offset type (e.g. Day or 'D') and
        offset magnitude (e.g., n = 3).
    closed : 'left' or 'right', optional
        Which side of bin interval is closed. Defaults to 'left'.
    base : int, optional
        For frequencies that evenly subdivide 1 day, the "origin" of the
        aggregated intervals. For example, for '5min' frequency, base could
        range from 0 through 4. Defaults to 0.

    Returns
    -------
    first : cftime.datetime
        Corrected starting datetime object for resampled CFTimeIndex range.
    last : cftime.datetime
        Corrected ending datetime object for resampled CFTimeIndex range.
    """
    if isinstance(offset, CFTIME_TICKS):
        first, last = _adjust_dates_anchored(first, last, offset,
                                             closed=closed, base=base)
        return first, last
    else:
        first = normalize_date(first)
        last = normalize_date(last)

    if closed == 'left':
        first = offset.rollback(first)
    else:
        first = first - offset

    last = last + offset
    return first, last


Instruction:
Explain what the following Python 3 code does
def _adjust_dates_anchored(first, last, offset, closed='right', base=0):

    base = base % offset.n
    start_day = normalize_date(first)
    base_td = type(offset)(n=base).as_timedelta()
    start_day += base_td
    foffset = exact_cftime_datetime_difference(
        start_day, first) % offset.as_timedelta()
    loffset = exact_cftime_datetime_difference(
        start_day, last) % offset.as_timedelta()
    if closed == 'right':
        if foffset.total_seconds() > 0:
            fresult = first - foffset
        else:
            fresult = first - offset.as_timedelta()

        if loffset.total_seconds() > 0:
            lresult = last + (offset.as_timedelta() - loffset)
        else:
            lresult = last
    else:
        if foffset.total_seconds() > 0:
            fresult = first - foffset
        else:
            fresult = first

        if loffset.total_seconds() > 0:
            lresult = last + (offset.as_timedelta() - loffset)
        else:
            lresult = last + offset.as_timedelta()
    return fresult, lresult

Response: Adjusts the dates of the first and last time series to fix resampling errors.


Instruction:
Write a Python 3 script to
exact computation of a and b.

Response:
def exact_cftime_datetime_difference(a, b):
    """Exact computation of b - a

    Assumes:

        a = a_0 + a_m
        b = b_0 + b_m

    Here a_0, and b_0 represent the input dates rounded
    down to the nearest second, and a_m, and b_m represent
    the remaining microseconds associated with date a and
    date b.

    We can then express the value of b - a as:

        b - a = (b_0 + b_m) - (a_0 + a_m) = b_0 - a_0 + b_m - a_m

    By construction, we know that b_0 - a_0 must be a round number
    of seconds.  Therefore we can take the result of b_0 - a_0 using
    ordinary cftime.datetime arithmetic and round to the nearest
    second.  b_m - a_m is the remainder, in microseconds, and we
    can simply add this to the rounded timedelta.

    Parameters
    ----------
    a : cftime.datetime
        Input datetime
    b : cftime.datetime
        Input datetime

    Returns
    -------
    datetime.timedelta
    """
    seconds = b.replace(microsecond=0) - a.replace(microsecond=0)
    seconds = int(round(seconds.total_seconds()))
    microseconds = b.microsecond - a.microsecond
    return datetime.timedelta(seconds=seconds, microseconds=microseconds)


Instruction:
How would you explain what the following Python 3 function does
def first_items(self, index):

        datetime_bins, labels = _get_time_bins(index, self.freq, self.closed,
                                               self.label, self.base)
        if self.loffset is not None:
            if isinstance(self.loffset, datetime.timedelta):
                labels = labels + self.loffset
            else:
                labels = labels + to_offset(self.loffset)

        # check binner fits data
        if index[0] < datetime_bins[0]:
            raise ValueError("Value falls before first bin")
        if index[-1] > datetime_bins[-1]:
            raise ValueError("Value falls after last bin")

        integer_bins = np.searchsorted(
            index, datetime_bins, side=self.closed)[:-1]
        first_items = pd.Series(integer_bins, labels)

        # Mask duplicate values with NaNs, preserving the last values
        non_duplicate = ~first_items.duplicated('last')
        return first_items.where(non_duplicate)

Response: Meant to reproduce the results of the following


Instruction:
Here you have a function in Python 3, explain what it does
def align(*objects, **kwargs):
    join = kwargs.pop('join', 'inner')
    copy = kwargs.pop('copy', True)
    indexes = kwargs.pop('indexes', None)
    exclude = kwargs.pop('exclude', _DEFAULT_EXCLUDE)
    if indexes is None:
        indexes = {}
    if kwargs:
        raise TypeError('align() got unexpected keyword arguments: %s'
                        % list(kwargs))

    if not indexes and len(objects) == 1:
        # fast path for the trivial case
        obj, = objects
        return (obj.copy(deep=copy),)

    all_indexes = defaultdict(list)
    unlabeled_dim_sizes = defaultdict(set)
    for obj in objects:
        for dim in obj.dims:
            if dim not in exclude:
                try:
                    index = obj.indexes[dim]
                except KeyError:
                    unlabeled_dim_sizes[dim].add(obj.sizes[dim])
                else:
                    all_indexes[dim].append(index)

    # We don't reindex over dimensions with all equal indexes for two reasons:
    # - It's faster for the usual case (already aligned objects).
    # - It ensures it's possible to do operations that don't require alignment
    #   on indexes with duplicate values (which cannot be reindexed with
    #   pandas). This is useful, e.g., for overwriting such duplicate indexes.
    joiner = _get_joiner(join)
    joined_indexes = {}
    for dim, matching_indexes in all_indexes.items():
        if dim in indexes:
            index = utils.safe_cast_to_index(indexes[dim])
            if (any(not index.equals(other) for other in matching_indexes) or
                    dim in unlabeled_dim_sizes):
                joined_indexes[dim] = index
        else:
            if (any(not matching_indexes[0].equals(other)
                    for other in matching_indexes[1:]) or
                    dim in unlabeled_dim_sizes):
                if join == 'exact':
                    raise ValueError(
                        'indexes along dimension {!r} are not equal'
                        .format(dim))
                index = joiner(matching_indexes)
                joined_indexes[dim] = index
            else:
                index = matching_indexes[0]

        if dim in unlabeled_dim_sizes:
            unlabeled_sizes = unlabeled_dim_sizes[dim]
            labeled_size = index.size
            if len(unlabeled_sizes | {labeled_size}) > 1:
                raise ValueError(
                    'arguments without labels along dimension %r cannot be '
                    'aligned because they have different dimension size(s) %r '
                    'than the size of the aligned dimension labels: %r'
                    % (dim, unlabeled_sizes, labeled_size))

    for dim in unlabeled_dim_sizes:
        if dim not in all_indexes:
            sizes = unlabeled_dim_sizes[dim]
            if len(sizes) > 1:
                raise ValueError(
                    'arguments without labels along dimension %r cannot be '
                    'aligned because they have different dimension sizes: %r'
                    % (dim, sizes))

    result = []
    for obj in objects:
        valid_indexers = {k: v for k, v in joined_indexes.items()
                          if k in obj.dims}
        if not valid_indexers:
            # fast path for no reindexing necessary
            new_obj = obj.copy(deep=copy)
        else:
            new_obj = obj.reindex(copy=copy, **valid_indexers)
        new_obj.encoding = obj.encoding
        result.append(new_obj)

    return tuple(result)

Response: Aligns the objects in the input list with the same size as the input list.


Instruction:
Can you generate the documentation for the following Python 3 function
def deep_align(objects, join='inner', copy=True, indexes=None,
               exclude=frozenset(), raise_on_invalid=True):
    """Align objects for merging, recursing into dictionary values.

    This function is not public API.
    """
    from .dataarray import DataArray
    from .dataset import Dataset

    if indexes is None:
        indexes = {}

    def is_alignable(obj):
        return isinstance(obj, (DataArray, Dataset))

    positions = []
    keys = []
    out = []
    targets = []
    no_key = object()
    not_replaced = object()
    for n, variables in enumerate(objects):
        if is_alignable(variables):
            positions.append(n)
            keys.append(no_key)
            targets.append(variables)
            out.append(not_replaced)
        elif is_dict_like(variables):
            for k, v in variables.items():
                if is_alignable(v) and k not in indexes:
                    # Skip variables in indexes for alignment, because these
                    # should to be overwritten instead:
                    # https://github.com/pydata/xarray/issues/725
                    positions.append(n)
                    keys.append(k)
                    targets.append(v)
            out.append(OrderedDict(variables))
        elif raise_on_invalid:
            raise ValueError('object to align is neither an xarray.Dataset, '
                             'an xarray.DataArray nor a dictionary: %r'
                             % variables)
        else:
            out.append(variables)

    aligned = align(*targets, join=join, copy=copy, indexes=indexes,
                    exclude=exclude)

    for position, key, aligned_obj in zip(positions, keys, aligned):
        if key is no_key:
            out[position] = aligned_obj
        else:
            out[position][key] = aligned_obj

    # something went wrong: we should have replaced all sentinel values
    assert all(arg is not not_replaced for arg in out)

    return out

Response: Align objects for merging into dictionary values.


Instruction:
Can you tell what is the following Python 3 function doing
def reindex_like_indexers(target, other):
    indexers = {k: v for k, v in other.indexes.items() if k in target.dims}

    for dim in other.dims:
        if dim not in indexers and dim in target.dims:
            other_size = other.sizes[dim]
            target_size = target.sizes[dim]
            if other_size != target_size:
                raise ValueError('different size for unlabeled '
                                 'dimension on argument %r: %r vs %r'
                                 % (dim, other_size, target_size))
    return indexers

Response: Extract indexers to align target with other.


Instruction:
Given the following Python 3 function, write the documentation
def reindex_variables(
    variables: Mapping[Any, Variable],
    sizes: Mapping[Any, int],
    indexes: Mapping[Any, pd.Index],
    indexers: Mapping,
    method: Optional[str] = None,
    tolerance: Any = None,
    copy: bool = True,
) -> 'Tuple[OrderedDict[Any, Variable], OrderedDict[Any, pd.Index]]':
    """Conform a dictionary of aligned variables onto a new set of variables,
    filling in missing values with NaN.

    Not public API.

    Parameters
    ----------
    variables : dict-like
        Dictionary of xarray.Variable objects.
    sizes : dict-like
        Dictionary from dimension names to integer sizes.
    indexes : dict-like
        Dictionary of indexes associated with variables.
    indexers : dict
        Dictionary with keys given by dimension names and values given by
        arrays of coordinates tick labels. Any mis-matched coordinate values
        will be filled in with NaN, and any mis-matched dimension names will
        simply be ignored.
    method : {None, 'nearest', 'pad'/'ffill', 'backfill'/'bfill'}, optional
        Method to use for filling index values in ``indexers`` not found in
        this dataset:
          * None (default): don't fill gaps
          * pad / ffill: propagate last valid index value forward
          * backfill / bfill: propagate next valid index value backward
          * nearest: use nearest valid index value
    tolerance : optional
        Maximum distance between original and new labels for inexact matches.
        The values of the index at the matching locations must satisfy the
        equation ``abs(index[indexer] - target) <= tolerance``.
    copy : bool, optional
        If ``copy=True``, data in the return values is always copied. If
        ``copy=False`` and reindexing is unnecessary, or can be performed
        with only slice operations, then the output may share memory with
        the input. In either case, new xarray objects are always returned.

    Returns
    -------
    reindexed : OrderedDict
        Dict of reindexed variables.
    new_indexes : OrderedDict
        Dict of indexes associated with the reindexed variables.
    """
    from .dataarray import DataArray

    # create variables for the new dataset
    reindexed = OrderedDict()  # type: OrderedDict[Any, Variable]

    # build up indexers for assignment along each dimension
    int_indexers = {}
    new_indexes = OrderedDict(indexes)
    masked_dims = set()
    unchanged_dims = set()

    for dim, indexer in indexers.items():
        if isinstance(indexer, DataArray) and indexer.dims != (dim,):
            warnings.warn(
                "Indexer has dimensions {0:s} that are different "
                "from that to be indexed along {1:s}. "
                "This will behave differently in the future.".format(
                    str(indexer.dims), dim),
                FutureWarning, stacklevel=3)

        target = new_indexes[dim] = utils.safe_cast_to_index(indexers[dim])

        if dim in indexes:
            index = indexes[dim]

            if not index.is_unique:
                raise ValueError(
                    'cannot reindex or align along dimension %r because the '
                    'index has duplicate values' % dim)

            int_indexer = get_indexer_nd(index, target, method, tolerance)

            # We uses negative values from get_indexer_nd to signify
            # values that are missing in the index.
            if (int_indexer < 0).any():
                masked_dims.add(dim)
            elif np.array_equal(int_indexer, np.arange(len(index))):
                unchanged_dims.add(dim)

            int_indexers[dim] = int_indexer

        if dim in variables:
            var = variables[dim]
            args = (var.attrs, var.encoding)  # type: tuple
        else:
            args = ()
        reindexed[dim] = IndexVariable((dim,), target, *args)

    for dim in sizes:
        if dim not in indexes and dim in indexers:
            existing_size = sizes[dim]
            new_size = indexers[dim].size
            if existing_size != new_size:
                raise ValueError(
                    'cannot reindex or align along dimension %r without an '
                    'index because its size %r is different from the size of '
                    'the new index %r' % (dim, existing_size, new_size))

    for name, var in variables.items():
        if name not in indexers:
            key = tuple(slice(None)
                        if d in unchanged_dims
                        else int_indexers.get(d, slice(None))
                        for d in var.dims)
            needs_masking = any(d in masked_dims for d in var.dims)

            if needs_masking:
                new_var = var._getitem_with_mask(key)
            elif all(is_full_slice(k) for k in key):
                # no reindexing necessary
                # here we need to manually deal with copying data, since
                # we neither created a new ndarray nor used fancy indexing
                new_var = var.copy(deep=copy)
            else:
                new_var = var[key]

            reindexed[name] = new_var

    return reindexed, new_indexes

Response: Conform a dictionary of aligned variables onto a new set of variables.


Instruction:
Can you tell what is the following Python 3 function doing
def assert_coordinate_consistent(obj, coords):
    for k in obj.dims:
        # make sure there are no conflict in dimension coordinates
        if k in coords and k in obj.coords:
            if not coords[k].equals(obj[k].variable):
                raise IndexError(
                    'dimension coordinate {!r} conflicts between '
                    'indexed and indexing objects:\n{}\nvs.\n{}'
                    .format(k, obj[k], coords[k]))

Response:
Maeke sure the dimension coordinate of obj is
    consistent with coords.


Instruction:
Explain what the following Python 3 code does
def remap_label_indexers(obj, indexers=None, method=None, tolerance=None,
                         **indexers_kwargs):
    """
    Remap **indexers from obj.coords.
    If indexer is an instance of DataArray and it has coordinate, then this
    coordinate will be attached to pos_indexers.

    Returns
    -------
    pos_indexers: Same type of indexers.
        np.ndarray or Variable or DataArra
    new_indexes: mapping of new dimensional-coordinate.
    """
    from .dataarray import DataArray
    indexers = either_dict_or_kwargs(
        indexers, indexers_kwargs, 'remap_label_indexers')

    v_indexers = {k: v.variable.data if isinstance(v, DataArray) else v
                  for k, v in indexers.items()}

    pos_indexers, new_indexes = indexing.remap_label_indexers(
        obj, v_indexers, method=method, tolerance=tolerance
    )
    # attach indexer's coordinate to pos_indexers
    for k, v in indexers.items():
        if isinstance(v, Variable):
            pos_indexers[k] = Variable(v.dims, pos_indexers[k])
        elif isinstance(v, DataArray):
            # drop coordinates found in indexers since .sel() already
            # ensures alignments
            coords = OrderedDict((k, v) for k, v in v._coords.items()
                                 if k not in indexers)
            pos_indexers[k] = DataArray(pos_indexers[k],
                                        coords=coords, dims=v.dims)
    return pos_indexers, new_indexes

Response: Remap indexers from obj. coords to new dimensions.


Instruction:
Implement a function in Python 3 to
convert all index coordinates into a pandas. Index.

Response:
def to_index(self, ordered_dims=None):
        """Convert all index coordinates into a :py:class:`pandas.Index`.

        Parameters
        ----------
        ordered_dims : sequence, optional
            Possibly reordered version of this object's dimensions indicating
            the order in which dimensions should appear on the result.

        Returns
        -------
        pandas.Index
            Index subclass corresponding to the outer-product of all dimension
            coordinates. This will be a MultiIndex if this object is has more
            than more dimension.
        """
        if ordered_dims is None:
            ordered_dims = self.dims
        elif set(ordered_dims) != set(self.dims):
            raise ValueError('ordered_dims must match dims, but does not: '
                             '{} vs {}'.format(ordered_dims, self.dims))

        if len(ordered_dims) == 0:
            raise ValueError('no valid index for a 0-dimensional object')
        elif len(ordered_dims) == 1:
            (dim,) = ordered_dims
            return self._data.get_index(dim)
        else:
            indexes = [self._data.get_index(k) for k in ordered_dims]
            names = list(ordered_dims)
            return pd.MultiIndex.from_product(indexes, names=names)


Instruction:
Given the following Python 3 function, write the documentation
def _merge_inplace(self, other):
        if other is None:
            yield
        else:
            # don't include indexes in priority_vars, because we didn't align
            # first
            priority_vars = OrderedDict(
                kv for kv in self.variables.items() if kv[0] not in self.dims)
            variables = merge_coords_for_inplace_math(
                [self.variables, other.variables], priority_vars=priority_vars)
            yield
            self._update_coords(variables)

Response: For use with in - place binary arithmetic.


Instruction:
Write a Python 3 function that can
merge two sets of coordinates to create a new Dataset The method implements the logic used for joining coordinates in the result of a binary operation performed on xarray objects: - If two index coordinates conflict (are not equal), an exception is raised. You must align your data before passing it to this method. - If an index coordinate and a non-index coordinate conflict, the non- index coordinate is dropped. - If two non-index coordinates conflict, both are dropped. Parameters ---------- other : DatasetCoordinates or DataArrayCoordinates The coordinates from another dataset or data array. Returns ------- merged : Dataset A new Dataset with merged coordinates.

Response:
def merge(self, other):
        """Merge two sets of coordinates to create a new Dataset

        The method implements the logic used for joining coordinates in the
        result of a binary operation performed on xarray objects:

        - If two index coordinates conflict (are not equal), an exception is
          raised. You must align your data before passing it to this method.
        - If an index coordinate and a non-index coordinate conflict, the non-
          index coordinate is dropped.
        - If two non-index coordinates conflict, both are dropped.

        Parameters
        ----------
        other : DatasetCoordinates or DataArrayCoordinates
            The coordinates from another dataset or data array.

        Returns
        -------
        merged : Dataset
            A new Dataset with merged coordinates.
        """
        from .dataset import Dataset

        if other is None:
            return self.to_dataset()
        else:
            other_vars = getattr(other, 'variables', other)
            coords = expand_and_merge_variables([self.variables, other_vars])
            return Dataset._from_vars_and_coord_names(coords, set(coords))


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _ipython_key_completions_(self):
        return [key for key in self._data._ipython_key_completions_()
                if key not in self._data.data_vars]

Response: Provide method for the key - completerions in IPython.


Instruction:
How would you implement a function in Python 3 that
wraps to apply bottleneck moving window funcs on dask arrays

Response:
def dask_rolling_wrapper(moving_func, a, window, min_count=None, axis=-1):
    '''wrapper to apply bottleneck moving window funcs on dask arrays'''
    dtype, fill_value = dtypes.maybe_promote(a.dtype)
    a = a.astype(dtype)
    # inputs for overlap
    if axis < 0:
        axis = a.ndim + axis
    depth = {d: 0 for d in range(a.ndim)}
    depth[axis] = (window + 1) // 2
    boundary = {d: fill_value for d in range(a.ndim)}
    # Create overlap array.
    ag = overlap(a, depth=depth, boundary=boundary)
    # apply rolling func
    out = ag.map_blocks(moving_func, window, min_count=min_count,
                        axis=axis, dtype=a.dtype)
    # trim array
    result = trim_internal(out, depth)
    return result


Instruction:
Can you tell what is the following Python 3 function doing
def rolling_window(a, axis, window, center, fill_value):
    orig_shape = a.shape
    if axis < 0:
        axis = a.ndim + axis
    depth = {d: 0 for d in range(a.ndim)}
    depth[axis] = int(window / 2)
    # For evenly sized window, we need to crop the first point of each block.
    offset = 1 if window % 2 == 0 else 0

    if depth[axis] > min(a.chunks[axis]):
        raise ValueError(
            "For window size %d, every chunk should be larger than %d, "
            "but the smallest chunk size is %d. Rechunk your array\n"
            "with a larger chunk size or a chunk size that\n"
            "more evenly divides the shape of your array." %
            (window, depth[axis], min(a.chunks[axis])))

    # Although dask.overlap pads values to boundaries of the array,
    # the size of the generated array is smaller than what we want
    # if center == False.
    if center:
        start = int(window / 2)  # 10 -> 5,  9 -> 4
        end = window - 1 - start
    else:
        start, end = window - 1, 0
    pad_size = max(start, end) + offset - depth[axis]
    drop_size = 0
    # pad_size becomes more than 0 when the overlapped array is smaller than
    # needed. In this case, we need to enlarge the original array by padding
    # before overlapping.
    if pad_size > 0:
        if pad_size < depth[axis]:
            # overlapping requires each chunk larger than depth. If pad_size is
            # smaller than the depth, we enlarge this and truncate it later.
            drop_size = depth[axis] - pad_size
            pad_size = depth[axis]
        shape = list(a.shape)
        shape[axis] = pad_size
        chunks = list(a.chunks)
        chunks[axis] = (pad_size, )
        fill_array = da.full(shape, fill_value, dtype=a.dtype, chunks=chunks)
        a = da.concatenate([fill_array, a], axis=axis)

    boundary = {d: fill_value for d in range(a.ndim)}

    # create overlap arrays
    ag = overlap(a, depth=depth, boundary=boundary)

    # apply rolling func
    def func(x, window, axis=-1):
        x = np.asarray(x)
        rolling = nputils._rolling_window(x, window, axis)
        return rolling[(slice(None), ) * axis + (slice(offset, None), )]

    chunks = list(a.chunks)
    chunks.append(window)
    out = ag.map_blocks(func, dtype=a.dtype, new_axis=a.ndim, chunks=chunks,
                        window=window, axis=axis)

    # crop boundary.
    index = (slice(None),) * axis + (slice(drop_size,
                                           drop_size + orig_shape[axis]), )
    return out[index]

Response: Dask s equivalence to np. utils. rolling_window


Instruction:
Write a Python 3 function for
determining the size of the zarr array based on the encoding and variable data.

Response:
def _determine_zarr_chunks(enc_chunks, var_chunks, ndim):
    """
    Given encoding chunks (possibly None) and variable chunks (possibly None)
    """

    # zarr chunk spec:
    # chunks : int or tuple of ints, optional
    #   Chunk shape. If not provided, will be guessed from shape and dtype.

    # if there are no chunks in encoding and the variable data is a numpy
    # array, then we let zarr use its own heuristics to pick the chunks
    if var_chunks is None and enc_chunks is None:
        return None

    # if there are no chunks in encoding but there are dask chunks, we try to
    # use the same chunks in zarr
    # However, zarr chunks needs to be uniform for each array
    # http://zarr.readthedocs.io/en/latest/spec/v1.html#chunks
    # while dask chunks can be variable sized
    # http://dask.pydata.org/en/latest/array-design.html#chunks
    if var_chunks and enc_chunks is None:
        if any(len(set(chunks[:-1])) > 1 for chunks in var_chunks):
            raise ValueError(
                "Zarr requires uniform chunk sizes except for final chunk."
                " Variable dask chunks %r are incompatible. Consider "
                "rechunking using `chunk()`." % (var_chunks,))
        if any((chunks[0] < chunks[-1]) for chunks in var_chunks):
            raise ValueError(
                "Final chunk of Zarr array must be the same size or smaller "
                "than the first. Variable Dask chunks %r are incompatible. "
                "Consider rechunking using `chunk()`." % var_chunks)
        # return the first chunk for each dimension
        return tuple(chunk[0] for chunk in var_chunks)

    # from here on, we are dealing with user-specified chunks in encoding
    # zarr allows chunks to be an integer, in which case it uses the same chunk
    # size on each dimension.
    # Here we re-implement this expansion ourselves. That makes the logic of
    # checking chunk compatibility easier

    if isinstance(enc_chunks, integer_types):
        enc_chunks_tuple = ndim * (enc_chunks,)
    else:
        enc_chunks_tuple = tuple(enc_chunks)

    if len(enc_chunks_tuple) != ndim:
        # throw away encoding chunks, start over
        return _determine_zarr_chunks(None, var_chunks, ndim)

    for x in enc_chunks_tuple:
        if not isinstance(x, int):
            raise TypeError("zarr chunks must be an int or a tuple of ints. "
                            "Instead found %r" % (enc_chunks_tuple,))

    # if there are chunks in encoding and the variable data is a numpy array,
    # we use the specified chunks
    if var_chunks is None:
        return enc_chunks_tuple

    # the hard case
    # DESIGN CHOICE: do not allow multiple dask chunks on a single zarr chunk
    # this avoids the need to get involved in zarr synchronization / locking
    # From zarr docs:
    #  "If each worker in a parallel computation is writing to a separate
    #   region of the array, and if region boundaries are perfectly aligned
    #   with chunk boundaries, then no synchronization is required."
    # TODO: incorporate synchronizer to allow writes from multiple dask
    # threads
    if var_chunks and enc_chunks_tuple:
        for zchunk, dchunks in zip(enc_chunks_tuple, var_chunks):
            for dchunk in dchunks[:-1]:
                if dchunk % zchunk:
                    raise NotImplementedError(
                        "Specified zarr chunks %r would overlap multiple dask "
                        "chunks %r. This is not implemented in xarray yet. "
                        " Consider rechunking the data using "
                        "`chunk()` or specifying different chunks in encoding."
                        % (enc_chunks_tuple, var_chunks))
            if dchunks[-1] > zchunk:
                raise ValueError(
                    "Final chunk of Zarr array must be the same size or "
                    "smaller than the first. The specified Zarr chunk "
                    "encoding is %r, but %r in variable Dask chunks %r is "
                    "incompatible. Consider rechunking using `chunk()`."
                    % (enc_chunks_tuple, dchunks, var_chunks))
        return enc_chunks_tuple

    raise AssertionError(
        "We should never get here. Function logic must be wrong.")


Instruction:
Make a summary of the following Python 3 code
def encode_zarr_variable(var, needs_copy=True, name=None):

    var = conventions.encode_cf_variable(var, name=name)

    # zarr allows unicode, but not variable-length strings, so it's both
    # simpler and more compact to always encode as UTF-8 explicitly.
    # TODO: allow toggling this explicitly via dtype in encoding.
    coder = coding.strings.EncodedStringCoder(allows_unicode=False)
    var = coder.encode(var, name=name)
    var = coding.strings.ensure_fixed_length_bytes(var)

    return var

Response: Encodes a variable into a zarr - compatible variable.


Instruction:
Can you write a function in Python 3 where it
loads and decode a dataset from a Zarr store.

Response:
def open_zarr(store, group=None, synchronizer=None, chunks='auto',
              decode_cf=True, mask_and_scale=True, decode_times=True,
              concat_characters=True, decode_coords=True,
              drop_variables=None, consolidated=False,
              overwrite_encoded_chunks=False, **kwargs):
    """Load and decode a dataset from a Zarr store.

    .. note:: Experimental
              The Zarr backend is new and experimental. Please report any
              unexpected behavior via github issues.

    The `store` object should be a valid store for a Zarr group. `store`
    variables must contain dimension metadata encoded in the
    `_ARRAY_DIMENSIONS` attribute.

    Parameters
    ----------
    store : MutableMapping or str
        A MutableMapping where a Zarr Group has been stored or a path to a
        directory in file system where a Zarr DirectoryStore has been stored.
    synchronizer : object, optional
        Array synchronizer provided to zarr
    group : str, obtional
        Group path. (a.k.a. `path` in zarr terminology.)
    chunks : int or dict or tuple or {None, 'auto'}, optional
        Chunk sizes along each dimension, e.g., ``5`` or
        ``{'x': 5, 'y': 5}``. If `chunks='auto'`, dask chunks are created
        based on the variable's zarr chunks. If `chunks=None`, zarr array
        data will lazily convert to numpy arrays upon access. This accepts
        all the chunk specifications as Dask does.
    overwrite_encoded_chunks: bool, optional
        Whether to drop the zarr chunks encoded for each variable when a
        dataset is loaded with specified chunk sizes (default: False)
    decode_cf : bool, optional
        Whether to decode these variables, assuming they were saved according
        to CF conventions.
    mask_and_scale : bool, optional
        If True, replace array values equal to `_FillValue` with NA and scale
        values according to the formula `original_values * scale_factor +
        add_offset`, where `_FillValue`, `scale_factor` and `add_offset` are
        taken from variable attributes (if they exist).  If the `_FillValue` or
        `missing_value` attribute contains multiple values a warning will be
        issued and all array values matching one of the multiple values will
        be replaced by NA.
    decode_times : bool, optional
        If True, decode times encoded in the standard NetCDF datetime format
        into datetime objects. Otherwise, leave them encoded as numbers.
    concat_characters : bool, optional
        If True, concatenate along the last dimension of character arrays to
        form string arrays. Dimensions will only be concatenated over (and
        removed) if they have no corresponding variable and if they are only
        used as the last dimension of character arrays.
    decode_coords : bool, optional
        If True, decode the 'coordinates' attribute to identify coordinates in
        the resulting dataset.
    drop_variables : string or iterable, optional
        A variable or list of variables to exclude from being parsed from the
        dataset. This may be useful to drop variables with problems or
        inconsistent values.
    consolidated : bool, optional
        Whether to open the store using zarr's consolidated metadata
        capability. Only works for stores that have already been consolidated.

    Returns
    -------
    dataset : Dataset
        The newly created dataset.

    See Also
    --------
    open_dataset

    References
    ----------
    http://zarr.readthedocs.io/
    """
    if 'auto_chunk' in kwargs:
        auto_chunk = kwargs.pop('auto_chunk')
        if auto_chunk:
            chunks = 'auto'  # maintain backwards compatibility
        else:
            chunks = None

        warnings.warn("auto_chunk is deprecated. Use chunks='auto' instead.",
                      FutureWarning, stacklevel=2)

    if kwargs:
        raise TypeError("open_zarr() got unexpected keyword arguments " +
                        ",".join(kwargs.keys()))

    if not isinstance(chunks, (int, dict)):
        if chunks != 'auto' and chunks is not None:
            raise ValueError("chunks must be an int, dict, 'auto', or None. "
                             "Instead found %s. " % chunks)

    if not decode_cf:
        mask_and_scale = False
        decode_times = False
        concat_characters = False
        decode_coords = False

    def maybe_decode_store(store, lock=False):
        ds = conventions.decode_cf(
            store, mask_and_scale=mask_and_scale, decode_times=decode_times,
            concat_characters=concat_characters, decode_coords=decode_coords,
            drop_variables=drop_variables)

        # TODO: this is where we would apply caching

        return ds

    # Zarr supports a wide range of access modes, but for now xarray either
    # reads or writes from a store, never both. For open_zarr, we only read
    mode = 'r'
    zarr_store = ZarrStore.open_group(store, mode=mode,
                                      synchronizer=synchronizer,
                                      group=group, consolidated=consolidated)
    ds = maybe_decode_store(zarr_store)

    # auto chunking needs to be here and not in ZarrStore because variable
    # chunks do not survive decode_cf
    # return trivial case
    if not chunks:
        return ds

    # adapted from Dataset.Chunk()
    if isinstance(chunks, int):
        chunks = dict.fromkeys(ds.dims, chunks)

    if isinstance(chunks, tuple) and len(chunks) == len(ds.dims):
        chunks = dict(zip(ds.dims, chunks))

    def get_chunk(name, var, chunks):
        chunk_spec = dict(zip(var.dims, var.encoding.get('chunks')))

        # Coordinate labels aren't chunked
        if var.ndim == 1 and var.dims[0] == name:
            return chunk_spec

        if chunks == 'auto':
            return chunk_spec

        for dim in var.dims:
            if dim in chunks:
                spec = chunks[dim]
                if isinstance(spec, int):
                    spec = (spec,)
                if isinstance(spec, (tuple, list)) and chunk_spec[dim]:
                    if any(s % chunk_spec[dim] for s in spec):
                        warnings.warn("Specified Dask chunks %r would "
                                      "separate Zarr chunk shape %r for "
                                      "dimension %r. This significantly "
                                      "degrades performance. Consider "
                                      "rechunking after loading instead."
                                      % (chunks[dim], chunk_spec[dim], dim),
                                      stacklevel=2)
                chunk_spec[dim] = chunks[dim]
        return chunk_spec

    def maybe_chunk(name, var, chunks):
        from dask.base import tokenize

        chunk_spec = get_chunk(name, var, chunks)

        if (var.ndim > 0) and (chunk_spec is not None):
            # does this cause any data to be read?
            token2 = tokenize(name, var._data)
            name2 = 'zarr-%s' % token2
            var = var.chunk(chunk_spec, name=name2, lock=None)
            if overwrite_encoded_chunks and var.chunks is not None:
                var.encoding['chunks'] = tuple(x[0] for x in var.chunks)
            return var
        else:
            return var

    variables = OrderedDict([(k, maybe_chunk(k, v, chunks))
                            for k, v in ds.variables.items()])
    return ds._replace_vars_and_dims(variables)


Instruction:
Write a Python 3 function for
extracting dimension sizes from a dictionary of variables.

Response:
def broadcast_dimension_size(
    variables: List[Variable],
) -> 'OrderedDict[Any, int]':
    """Extract dimension sizes from a dictionary of variables.

    Raises ValueError if any dimensions have different sizes.
    """
    dims = OrderedDict()  # type: OrderedDict[Any, int]
    for var in variables:
        for dim, size in zip(var.dims, var.shape):
            if dim in dims and size != dims[dim]:
                raise ValueError('index %r not aligned' % dim)
            dims[dim] = size
    return dims


Instruction:
Can you tell what is the following Python 3 function doing
def unique_variable(name, variables, compat='broadcast_equals'):
    # type: (Any, List[Variable], str) -> Variable
    """Return the unique variable from a list of variables or raise MergeError.

    Parameters
    ----------
    name : hashable
        Name for this variable.
    variables : list of xarray.Variable
        List of Variable objects, all of which go by the same name in different
        inputs.
    compat : {'identical', 'equals', 'broadcast_equals', 'no_conflicts'}, optional
        Type of equality check to use.

    Returns
    -------
    Variable to use in the result.

    Raises
    ------
    MergeError: if any of the variables are not equal.
    """  # noqa
    out = variables[0]
    if len(variables) > 1:
        combine_method = None

        if compat == 'minimal':
            compat = 'broadcast_equals'

        if compat == 'broadcast_equals':
            dim_lengths = broadcast_dimension_size(variables)
            out = out.set_dims(dim_lengths)

        if compat == 'no_conflicts':
            combine_method = 'fillna'

        for var in variables[1:]:
            if not getattr(out, compat)(var):
                raise MergeError('conflicting values for variable %r on '
                                 'objects to be combined:\n'
                                 'first value: %r\nsecond value: %r'
                                 % (name, out, var))
            if combine_method:
                # TODO: add preservation of attrs into fillna
                out = getattr(out, combine_method)(var)
                out.attrs = var.attrs

    return out

Response: Returns the unique variable from a list of variables.


Instruction:
Explain what the following Python 3 code does
def merge_variables(
        list_of_variables_dicts,  # type: List[Mapping[Any, Variable]]
        priority_vars=None,       # type: Optional[Mapping[Any, Variable]]
        compat='minimal',         # type: str
):
    # type: (...) -> OrderedDict[Any, Variable]
    """Merge dicts of variables, while resolving conflicts appropriately.

    Parameters
    ----------
    lists_of_variables_dicts : list of mappings with Variable values
        List of mappings for which each value is a xarray.Variable object.
    priority_vars : mapping with Variable or None values, optional
        If provided, variables are always taken from this dict in preference to
        the input variable dictionaries, without checking for conflicts.
    compat : {'identical', 'equals', 'broadcast_equals', 'minimal', 'no_conflicts'}, optional
        Type of equality check to use when checking for conflicts.

    Returns
    -------
    OrderedDict with keys taken by the union of keys on list_of_variable_dicts,
    and Variable values corresponding to those that should be found on the
    merged result.
    """  # noqa
    if priority_vars is None:
        priority_vars = {}

    _assert_compat_valid(compat)
    dim_compat = min(compat, 'equals', key=_VALID_COMPAT.get)

    lookup = OrderedDefaultDict(list)
    for variables in list_of_variables_dicts:
        for name, var in variables.items():
            lookup[name].append(var)

    # n.b. it's important to fill up merged in the original order in which
    # variables appear
    merged = OrderedDict()  # type: OrderedDict[Any, Variable]

    for name, var_list in lookup.items():
        if name in priority_vars:
            # one of these arguments (e.g., the first for in-place arithmetic
            # or the second for Dataset.update) takes priority
            merged[name] = priority_vars[name]
        else:
            dim_variables = [var for var in var_list if (name,) == var.dims]
            if dim_variables:
                # if there are dimension coordinates, these must be equal (or
                # identical), and they take priority over non-dimension
                # coordinates
                merged[name] = unique_variable(name, dim_variables, dim_compat)
            else:
                try:
                    merged[name] = unique_variable(name, var_list, compat)
                except MergeError:
                    if compat != 'minimal':
                        # we need more than "minimal" compatibility (for which
                        # we drop conflicting coordinates)
                        raise

    return merged

Response: Merges the variables in the list of variables_dicts into a single dict.


Instruction:
How would you implement a function in Python 3 that
gives a list of dicts with xarray object values expand the values.

Response:
def expand_variable_dicts(
    list_of_variable_dicts: 'List[Union[Dataset, OrderedDict]]',
) -> 'List[Mapping[Any, Variable]]':
    """Given a list of dicts with xarray object values, expand the values.

    Parameters
    ----------
    list_of_variable_dicts : list of dict or Dataset objects
        Each value for the mappings must be of the following types:
        - an xarray.Variable
        - a tuple `(dims, data[, attrs[, encoding]])` that can be converted in
          an xarray.Variable
        - or an xarray.DataArray

    Returns
    -------
    A list of ordered dictionaries corresponding to inputs, or coordinates from
    an input's values. The values of each ordered dictionary are all
    xarray.Variable objects.
    """
    from .dataarray import DataArray
    from .dataset import Dataset

    var_dicts = []

    for variables in list_of_variable_dicts:
        if isinstance(variables, Dataset):
            var_dicts.append(variables.variables)
            continue

        # append coords to var_dicts before appending sanitized_vars,
        # because we want coords to appear first
        sanitized_vars = OrderedDict()  # type: OrderedDict[Any, Variable]

        for name, var in variables.items():
            if isinstance(var, DataArray):
                # use private API for speed
                coords = var._coords.copy()
                # explicitly overwritten variables should take precedence
                coords.pop(name, None)
                var_dicts.append(coords)

            var = as_variable(var, name=name)
            sanitized_vars[name] = var

        var_dicts.append(sanitized_vars)

    return var_dicts


Instruction:
Create a Python 3 function for
giving a list of dicts with xarray object values identify coordinates.

Response:
def determine_coords(list_of_variable_dicts):
    # type: (List[Dict]) -> Tuple[Set, Set]
    """Given a list of dicts with xarray object values, identify coordinates.

    Parameters
    ----------
    list_of_variable_dicts : list of dict or Dataset objects
        Of the same form as the arguments to expand_variable_dicts.

    Returns
    -------
    coord_names : set of variable names
    noncoord_names : set of variable names
        All variable found in the input should appear in either the set of
        coordinate or non-coordinate names.
    """
    from .dataarray import DataArray
    from .dataset import Dataset

    coord_names = set()  # type: set
    noncoord_names = set()  # type: set

    for variables in list_of_variable_dicts:
        if isinstance(variables, Dataset):
            coord_names.update(variables.coords)
            noncoord_names.update(variables.data_vars)
        else:
            for name, var in variables.items():
                if isinstance(var, DataArray):
                    coords = set(var._coords)  # use private API for speed
                    # explicitly overwritten variables should take precedence
                    coords.discard(name)
                    coord_names.update(coords)

    return coord_names, noncoord_names


Instruction:
Can you generate the documentation for the following Python 3 function
def coerce_pandas_values(objects):
    from .dataset import Dataset
    from .dataarray import DataArray

    out = []
    for obj in objects:
        if isinstance(obj, Dataset):
            variables = obj
        else:
            variables = OrderedDict()
            if isinstance(obj, PANDAS_TYPES):
                obj = OrderedDict(obj.iteritems())
            for k, v in obj.items():
                if isinstance(v, PANDAS_TYPES):
                    v = DataArray(v)
                variables[k] = v
        out.append(variables)
    return out

Response: Convert pandas values found in a list of labeled objects into native xarray objects.


Instruction:
Create a Python 3 function to
merge coordinate variables without worrying about alignment. This function is used for merging variables in coordinates.py.

Response:
def merge_coords_for_inplace_math(objs, priority_vars=None):
    """Merge coordinate variables without worrying about alignment.

    This function is used for merging variables in coordinates.py.
    """
    expanded = expand_variable_dicts(objs)
    variables = merge_variables(expanded, priority_vars)
    assert_unique_multiindex_level_names(variables)
    return variables


Instruction:
Write a Python 3 function for
extracting the priority variable from a list of mappings. We need this method because in some cases the priority argument itself might have conflicting values (e.g., if it is a dict with two DataArray values with conflicting coordinate values). Parameters ---------- objects : list of dictionaries of variables Dictionaries in which to find the priority variables. priority_arg : int or None Integer object whose variable should take priority. compat : {'identical', 'equals', 'broadcast_equals', 'no_conflicts'}, optional Compatibility checks to use when merging variables. Returns ------- None, if priority_arg is None, or an OrderedDict with Variable objects as values indicating priority variables.

Response:
def _get_priority_vars(objects, priority_arg, compat='equals'):
    """Extract the priority variable from a list of mappings.

    We need this method because in some cases the priority argument itself
    might have conflicting values (e.g., if it is a dict with two DataArray
    values with conflicting coordinate values).

    Parameters
    ----------
    objects : list of dictionaries of variables
        Dictionaries in which to find the priority variables.
    priority_arg : int or None
        Integer object whose variable should take priority.
    compat : {'identical', 'equals', 'broadcast_equals', 'no_conflicts'}, optional
        Compatibility checks to use when merging variables.

    Returns
    -------
    None, if priority_arg is None, or an OrderedDict with Variable objects as
    values indicating priority variables.
    """  # noqa
    if priority_arg is None:
        priority_vars = {}
    else:
        expanded = expand_variable_dicts([objects[priority_arg]])
        priority_vars = merge_variables(expanded, compat=compat)
    return priority_vars


Instruction:
Write a Python 3 function for
expanding variables with worrying about alignment.

Response:
def expand_and_merge_variables(objs, priority_arg=None):
    """Merge coordinate variables without worrying about alignment.

    This function is used for merging variables in computation.py.
    """
    expanded = expand_variable_dicts(objs)
    priority_vars = _get_priority_vars(objs, priority_arg)
    variables = merge_variables(expanded, priority_vars)
    return variables


Instruction:
Write a Python 3 function for
merging coordinate variables. See merge_core below for argument descriptions. This works similarly to merge_core, except everything we don't worry about whether variables are coordinates or not.

Response:
def merge_coords(objs, compat='minimal', join='outer', priority_arg=None,
                 indexes=None):
    """Merge coordinate variables.

    See merge_core below for argument descriptions. This works similarly to
    merge_core, except everything we don't worry about whether variables are
    coordinates or not.
    """
    _assert_compat_valid(compat)
    coerced = coerce_pandas_values(objs)
    aligned = deep_align(coerced, join=join, copy=False, indexes=indexes)
    expanded = expand_variable_dicts(aligned)
    priority_vars = _get_priority_vars(aligned, priority_arg, compat=compat)
    variables = merge_variables(expanded, priority_vars, compat=compat)
    assert_unique_multiindex_level_names(variables)

    return variables


Instruction:
Can you implement a function in Python 3 that
uses in Dataset. __init__.

Response:
def merge_data_and_coords(data, coords, compat='broadcast_equals',
                          join='outer'):
    """Used in Dataset.__init__."""
    objs = [data, coords]
    explicit_coords = coords.keys()
    indexes = dict(extract_indexes(coords))
    return merge_core(objs, compat, join, explicit_coords=explicit_coords,
                      indexes=indexes)


Instruction:
How would you implement a function in Python 3 that
yields the name & index of valid indexes from a mapping of coords

Response:
def extract_indexes(coords):
    """Yields the name & index of valid indexes from a mapping of coords"""
    for name, variable in coords.items():
        variable = as_variable(variable, name=name)
        if variable.dims == (name,):
            yield name, variable.to_index()


Instruction:
Create a Python 3 function for
validating explicit coordinate names/dims. Raise a MergeError if an explicit coord shares a name with a dimension but is comprised of arbitrary dimensions.

Response:
def assert_valid_explicit_coords(variables, dims, explicit_coords):
    """Validate explicit coordinate names/dims.

    Raise a MergeError if an explicit coord shares a name with a dimension
    but is comprised of arbitrary dimensions.
    """
    for coord_name in explicit_coords:
        if coord_name in dims and variables[coord_name].dims != (coord_name,):
            raise MergeError(
                'coordinate %s shares a name with a dataset dimension, but is '
                'not a 1D variable along that dimension. This is disallowed '
                'by the xarray data model.' % coord_name)


Instruction:
Can you tell what is the following Python 3 function doing
def merge_core(objs,
               compat='broadcast_equals',
               join='outer',
               priority_arg=None,
               explicit_coords=None,
               indexes=None):
    """Core logic for merging labeled objects.

    This is not public API.

    Parameters
    ----------
    objs : list of mappings
        All values must be convertable to labeled arrays.
    compat : {'identical', 'equals', 'broadcast_equals', 'no_conflicts'}, optional
        Compatibility checks to use when merging variables.
    join : {'outer', 'inner', 'left', 'right'}, optional
        How to combine objects with different indexes.
    priority_arg : integer, optional
        Optional argument in `objs` that takes precedence over the others.
    explicit_coords : set, optional
        An explicit list of variables from `objs` that are coordinates.
    indexes : dict, optional
        Dictionary with values given by pandas.Index objects.

    Returns
    -------
    variables : OrderedDict
        Ordered dictionary of Variable objects.
    coord_names : set
        Set of coordinate names.
    dims : dict
        Dictionary mapping from dimension names to sizes.

    Raises
    ------
    MergeError if the merge cannot be done successfully.
    """  # noqa
    from .dataset import calculate_dimensions

    _assert_compat_valid(compat)

    coerced = coerce_pandas_values(objs)
    aligned = deep_align(coerced, join=join, copy=False, indexes=indexes)
    expanded = expand_variable_dicts(aligned)

    coord_names, noncoord_names = determine_coords(coerced)

    priority_vars = _get_priority_vars(aligned, priority_arg, compat=compat)
    variables = merge_variables(expanded, priority_vars, compat=compat)
    assert_unique_multiindex_level_names(variables)

    dims = calculate_dimensions(variables)

    if explicit_coords is not None:
        assert_valid_explicit_coords(variables, dims, explicit_coords)
        coord_names.update(explicit_coords)

    for dim, size in dims.items():
        if dim in variables:
            coord_names.add(dim)

    ambiguous_coords = coord_names.intersection(noncoord_names)
    if ambiguous_coords:
        raise MergeError('unable to determine if these variables should be '
                         'coordinates or not in the merged result: %s'
                         % ambiguous_coords)

    return variables, coord_names, dict(dims)

Response: This function is not public API. It will merge labeled arrays.


Instruction:
Can you create a Python 3 function that
merges any number of xarray objects into a single Dataset.

Response:
def merge(objects, compat='no_conflicts', join='outer'):
    """Merge any number of xarray objects into a single Dataset as variables.

    Parameters
    ----------
    objects : Iterable[Union[xarray.Dataset, xarray.DataArray, dict]]
        Merge together all variables from these objects. If any of them are
        DataArray objects, they must have a name.
    compat : {'identical', 'equals', 'broadcast_equals', 'no_conflicts'}, 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.
    join : {'outer', 'inner', 'left', 'right', 'exact'}, optional
        How to combine objects with different indexes.

    Returns
    -------
    Dataset
        Dataset with combined variables from each object.

    Examples
    --------
    >>> arrays = [xr.DataArray(n, name='var%d' % n) for n in range(5)]
    >>> xr.merge(arrays)
    <xarray.Dataset>
    Dimensions:  ()
    Coordinates:
        *empty*
    Data variables:
        var0     int64 0
        var1     int64 1
        var2     int64 2
        var3     int64 3
        var4     int64 4

    Raises
    ------
    xarray.MergeError
        If any variables with the same name have conflicting values.

    See also
    --------
    concat
    """  # noqa
    from .dataarray import DataArray
    from .dataset import Dataset

    dict_like_objects = [
        obj.to_dataset() if isinstance(obj, DataArray) else obj
        for obj in objects]

    variables, coord_names, dims = merge_core(dict_like_objects, compat, join)
    # TODO: don't always recompute indexes
    merged = Dataset._construct_direct(
        variables, coord_names, dims, indexes=None)

    return merged


Instruction:
Explain what the following Python 3 code does
def dataset_merge_method(dataset, other, overwrite_vars, compat, join):

    # we are locked into supporting overwrite_vars for the Dataset.merge
    # method due for backwards compatibility
    # TODO: consider deprecating it?

    if isinstance(overwrite_vars, str):
        overwrite_vars = set([overwrite_vars])
    overwrite_vars = set(overwrite_vars)

    if not overwrite_vars:
        objs = [dataset, other]
        priority_arg = None
    elif overwrite_vars == set(other):
        objs = [dataset, other]
        priority_arg = 1
    else:
        other_overwrite = OrderedDict()
        other_no_overwrite = OrderedDict()
        for k, v in other.items():
            if k in overwrite_vars:
                other_overwrite[k] = v
            else:
                other_no_overwrite[k] = v
        objs = [dataset, other_no_overwrite, other_overwrite]
        priority_arg = 2

    return merge_core(objs, compat, join, priority_arg=priority_arg)

Response: Guts of the Dataset. merge method.


Instruction:
Here you have a function in Python 3, explain what it does
def dataset_update_method(dataset, other):
    from .dataset import Dataset
    from .dataarray import DataArray

    if not isinstance(other, Dataset):
        other = OrderedDict(other)
        for key, value in other.items():
            if isinstance(value, DataArray):
                # drop conflicting coordinates
                coord_names = [c for c in value.coords
                               if c not in value.dims and c in dataset.coords]
                if coord_names:
                    other[key] = value.drop(coord_names)

    return merge_core([dataset, other], priority_arg=1,
                      indexes=dataset.indexes)

Response: Guts of the Dataset. update method.


Instruction:
Can you create a Python 3 function that
replaces nan in a by val and returns the replaced array and the nan position

Response:
def _replace_nan(a, val):
    """
    replace nan in a by val, and returns the replaced array and the nan
    position
    """
    mask = isnull(a)
    return where_method(val, mask, a), mask


Instruction:
How would you explain what the following Python 3 function does
def _maybe_null_out(result, axis, mask, min_count=1):
    if hasattr(axis, '__len__'):  # if tuple or list
        raise ValueError('min_count is not available for reduction '
                         'with more than one dimensions.')

    if axis is not None and getattr(result, 'ndim', False):
        null_mask = (mask.shape[axis] - mask.sum(axis) - min_count) < 0
        if null_mask.any():
            dtype, fill_value = dtypes.maybe_promote(result.dtype)
            result = result.astype(dtype)
            result[null_mask] = fill_value

    elif getattr(result, 'dtype', None) not in dtypes.NAT_TYPES:
        null_mask = mask.size - mask.sum()
        if null_mask < min_count:
            result = np.nan

    return result

Response: Internal function to handle null out of an array.


Instruction:
Can you generate the documentation for the following Python 3 function
def _disable_auto_decode_variable(var):
    var.set_auto_maskandscale(False)

    # only added in netCDF4-python v1.2.8
    with suppress(AttributeError):
        var.set_auto_chartostring(False)

Response: Disable automatic decoding on a netCDF4. Variable.


Instruction:
Write a Python 3 function for
returning an appropriate positive infinity value for this dtype.

Response:
def get_pos_infinity(dtype):
    """Return an appropriate positive infinity for this dtype.

    Parameters
    ----------
    dtype : np.dtype

    Returns
    -------
    fill_value : positive infinity value corresponding to this dtype.
    """
    if issubclass(dtype.type, (np.floating, np.integer)):
        return np.inf

    if issubclass(dtype.type, np.complexfloating):
        return np.inf + 1j * np.inf

    return INF


Instruction:
Make a summary of the following Python 3 code
def get_neg_infinity(dtype):
    if issubclass(dtype.type, (np.floating, np.integer)):
        return -np.inf

    if issubclass(dtype.type, np.complexfloating):
        return -np.inf - 1j * np.inf

    return NINF

Response: Return an appropriate positive infinity value for this dtype.


Instruction:
Can you tell what is the following Python 3 function doing
def is_datetime_like(dtype):
    return (np.issubdtype(dtype, np.datetime64) or
            np.issubdtype(dtype, np.timedelta64))

Response: Check if a dtype is a subclass of the numpy datetime types


Instruction:
Can you tell what is the following Python 3 function doing
def result_type(*arrays_and_dtypes):
    types = {np.result_type(t).type for t in arrays_and_dtypes}

    for left, right in PROMOTE_TO_OBJECT:
        if (any(issubclass(t, left) for t in types) and
                any(issubclass(t, right) for t in types)):
            return np.dtype(object)

    return np.result_type(*arrays_and_dtypes)

Response: Like np. result_type but with type promotion rules matching pandas.


Instruction:
How would you explain what the following Python 3 function does
def _parse_envi(meta):

    def parsevec(s):
        return np.fromstring(s.strip('{}'), dtype='float', sep=',')

    def default(s):
        return s.strip('{}')

    parse = {'wavelength': parsevec,
             'fwhm': parsevec}
    parsed_meta = {k: parse.get(k, default)(v) for k, v in meta.items()}
    return parsed_meta

Response: Parse the ENVI metadata into a dictionary of dicts.


Instruction:
Here you have a function in Python 3, explain what it does
def open_rasterio(filename, parse_coordinates=None, chunks=None, cache=None,
                  lock=None):
    """Open a file with rasterio (experimental).

    This should work with any file that rasterio can open (most often:
    geoTIFF). The x and y coordinates are generated automatically from the
    file's geoinformation, shifted to the center of each pixel (see
    `"PixelIsArea" Raster Space
    <http://web.archive.org/web/20160326194152/http://remotesensing.org/geotiff/spec/geotiff2.5.html#2.5.2>`_
    for more information).

    You can generate 2D coordinates from the file's attributes with::

        from affine import Affine
        da = xr.open_rasterio('path_to_file.tif')
        transform = Affine.from_gdal(*da.attrs['transform'])
        nx, ny = da.sizes['x'], da.sizes['y']
        x, y = np.meshgrid(np.arange(nx)+0.5, np.arange(ny)+0.5) * transform

    Parameters
    ----------
    filename : str, rasterio.DatasetReader, or rasterio.WarpedVRT
        Path to the file to open. Or already open rasterio dataset.
    parse_coordinates : bool, optional
        Whether to parse the x and y coordinates out of the file's
        ``transform`` attribute or not. The default is to automatically
        parse the coordinates only if they are rectilinear (1D).
        It can be useful to set ``parse_coordinates=False``
        if your files are very large or if you don't need the coordinates.
    chunks : int, tuple or dict, optional
        Chunk sizes along each dimension, e.g., ``5``, ``(5, 5)`` or
        ``{'x': 5, 'y': 5}``. If chunks is provided, it used to load the new
        DataArray into a dask array.
    cache : bool, optional
        If True, cache data loaded from the underlying datastore in memory as
        NumPy arrays when accessed to avoid reading from the underlying data-
        store multiple times. Defaults to True unless you specify the `chunks`
        argument to use dask, in which case it defaults to False.
    lock : False, True or threading.Lock, optional
        If chunks is provided, this argument is passed on to
        :py:func:`dask.array.from_array`. By default, a global lock is
        used to avoid issues with concurrent access to the same file when using
        dask's multithreaded backend.

    Returns
    -------
    data : DataArray
        The newly created DataArray.
    """
    import rasterio
    from rasterio.vrt import WarpedVRT
    vrt_params = None
    if isinstance(filename, rasterio.io.DatasetReader):
        filename = filename.name
    elif isinstance(filename, rasterio.vrt.WarpedVRT):
        vrt = filename
        filename = vrt.src_dataset.name
        vrt_params = dict(crs=vrt.crs.to_string(),
                          resampling=vrt.resampling,
                          src_nodata=vrt.src_nodata,
                          dst_nodata=vrt.dst_nodata,
                          tolerance=vrt.tolerance,
                          transform=vrt.transform,
                          width=vrt.width,
                          height=vrt.height,
                          warp_extras=vrt.warp_extras)

    if lock is None:
        lock = RASTERIO_LOCK

    manager = CachingFileManager(rasterio.open, filename, lock=lock, mode='r')
    riods = manager.acquire()
    if vrt_params is not None:
        riods = WarpedVRT(riods, **vrt_params)

    if cache is None:
        cache = chunks is None

    coords = OrderedDict()

    # Get bands
    if riods.count < 1:
        raise ValueError('Unknown dims')
    coords['band'] = np.asarray(riods.indexes)

    # Get coordinates
    if LooseVersion(rasterio.__version__) < '1.0':
        transform = riods.affine
    else:
        transform = riods.transform
    if transform.is_rectilinear:
        # 1d coordinates
        parse = True if parse_coordinates is None else parse_coordinates
        if parse:
            nx, ny = riods.width, riods.height
            # xarray coordinates are pixel centered
            x, _ = (np.arange(nx) + 0.5, np.zeros(nx) + 0.5) * transform
            _, y = (np.zeros(ny) + 0.5, np.arange(ny) + 0.5) * transform
            coords['y'] = y
            coords['x'] = x
    else:
        # 2d coordinates
        parse = False if (parse_coordinates is None) else parse_coordinates
        if parse:
            warnings.warn(
                "The file coordinates' transformation isn't "
                "rectilinear: xarray won't parse the coordinates "
                "in this case. Set `parse_coordinates=False` to "
                "suppress this warning.",
                RuntimeWarning, stacklevel=3)

    # Attributes
    attrs = dict()
    # Affine transformation matrix (always available)
    # This describes coefficients mapping pixel coordinates to CRS
    # For serialization store as tuple of 6 floats, the last row being
    # always (0, 0, 1) per definition (see
    # https://github.com/sgillies/affine)
    attrs['transform'] = tuple(transform)[:6]
    if hasattr(riods, 'crs') and riods.crs:
        # CRS is a dict-like object specific to rasterio
        # If CRS is not None, we convert it back to a PROJ4 string using
        # rasterio itself
        try:
            attrs['crs'] = riods.crs.to_proj4()
        except AttributeError:
            attrs['crs'] = riods.crs.to_string()
    if hasattr(riods, 'res'):
        # (width, height) tuple of pixels in units of CRS
        attrs['res'] = riods.res
    if hasattr(riods, 'is_tiled'):
        # Is the TIF tiled? (bool)
        # We cast it to an int for netCDF compatibility
        attrs['is_tiled'] = np.uint8(riods.is_tiled)
    if hasattr(riods, 'nodatavals'):
        # The nodata values for the raster bands
        attrs['nodatavals'] = tuple(
            np.nan if nodataval is None else nodataval
            for nodataval in riods.nodatavals)

    # Parse extra metadata from tags, if supported
    parsers = {'ENVI': _parse_envi}

    driver = riods.driver
    if driver in parsers:
        meta = parsers[driver](riods.tags(ns=driver))

        for k, v in meta.items():
            # Add values as coordinates if they match the band count,
            # as attributes otherwise
            if (isinstance(v, (list, np.ndarray))
                    and len(v) == riods.count):
                coords[k] = ('band', np.asarray(v))
            else:
                attrs[k] = v

    data = indexing.LazilyOuterIndexedArray(
        RasterioArrayWrapper(manager, lock, vrt_params))

    # this lets you write arrays loaded with rasterio
    data = indexing.CopyOnWriteArray(data)
    if cache and chunks is None:
        data = indexing.MemoryCachedArray(data)

    result = DataArray(data=data, dims=('band', 'y', 'x'),
                       coords=coords, attrs=attrs)

    if chunks is not None:
        from dask.base import tokenize
        # augment the token with the file modification time
        try:
            mtime = os.path.getmtime(filename)
        except OSError:
            # the filename is probably an s3 bucket rather than a regular file
            mtime = None
        token = tokenize(filename, mtime, chunks)
        name_prefix = 'open_rasterio-%s' % token
        result = result.chunk(chunks, name_prefix=name_prefix, token=token)

    # Make the file closeable
    result._file_obj = manager

    return result

Response: Open a file with rasterio.


Instruction:
Given the following Python 3 function, write the documentation
def _get_indexer(self, key):
        assert len(key) == 3, 'rasterio datasets should always be 3D'

        # bands cannot be windowed but they can be listed
        band_key = key[0]
        np_inds = []
        # bands (axis=0) cannot be windowed but they can be listed
        if isinstance(band_key, slice):
            start, stop, step = band_key.indices(self.shape[0])
            band_key = np.arange(start, stop, step)
        # be sure we give out a list
        band_key = (np.asarray(band_key) + 1).tolist()
        if isinstance(band_key, list):  # if band_key is not a scalar
            np_inds.append(slice(None))

        # but other dims can only be windowed
        window = []
        squeeze_axis = []
        for i, (k, n) in enumerate(zip(key[1:], self.shape[1:])):
            if isinstance(k, slice):
                # step is always positive. see indexing.decompose_indexer
                start, stop, step = k.indices(n)
                np_inds.append(slice(None, None, step))
            elif is_scalar(k):
                # windowed operations will always return an array
                # we will have to squeeze it later
                squeeze_axis.append(- (2 - i))
                start = k
                stop = k + 1
            else:
                start, stop = np.min(k), np.max(k) + 1
                np_inds.append(k - start)
            window.append((start, stop))

        if isinstance(key[1], np.ndarray) and isinstance(key[2], np.ndarray):
            # do outer-style indexing
            np_inds[-2:] = np.ix_(*np_inds[-2:])

        return band_key, tuple(window), tuple(squeeze_axis), tuple(np_inds)

Response: Get indexer for rasterio array.


Instruction:
How would you code a function in Python 3 to
group an array by its unique values.

Response:
def unique_value_groups(ar, sort=True):
    """Group an array by its unique values.

    Parameters
    ----------
    ar : array-like
        Input array. This will be flattened if it is not already 1-D.
    sort : boolean, optional
        Whether or not to sort unique values.

    Returns
    -------
    values : np.ndarray
        Sorted, unique values as returned by `np.unique`.
    indices : list of lists of int
        Each element provides the integer indices in `ar` with values given by
        the corresponding value in `unique_values`.
    """
    inverse, values = pd.factorize(ar, sort=sort)
    groups = [[] for _ in range(len(values))]
    for n, g in enumerate(inverse):
        if g >= 0:
            # pandas uses -1 to mark NaN, but doesn't include them in values
            groups[g].append(n)
    return values, groups


Instruction:
Make a summary of the following Python 3 code
def _consolidate_slices(slices):
    result = []
    last_slice = slice(None)
    for slice_ in slices:
        if not isinstance(slice_, slice):
            raise ValueError('list element is not a slice: %r' % slice_)
        if (result and last_slice.stop == slice_.start and
                _is_one_or_none(last_slice.step) and
                _is_one_or_none(slice_.step)):
            last_slice = slice(last_slice.start, slice_.stop, slice_.step)
            result[-1] = last_slice
        else:
            result.append(slice_)
            last_slice = slice_
    return result

Response: Consolidate adjacent slices in a list of slices.


Instruction:
How would you code a function in Python 3 to
like inverse_permutation but also handles slices.

Response:
def _inverse_permutation_indices(positions):
    """Like inverse_permutation, but also handles slices.

    Parameters
    ----------
    positions : list of np.ndarray or slice objects.
        If slice objects, all are assumed to be slices.

    Returns
    -------
    np.ndarray of indices or None, if no permutation is necessary.
    """
    if not positions:
        return None

    if isinstance(positions[0], slice):
        positions = _consolidate_slices(positions)
        if positions == slice(None):
            return None
        positions = [np.arange(sl.start, sl.stop, sl.step) for sl in positions]

    indices = nputils.inverse_permutation(np.concatenate(positions))
    return indices


Instruction:
Make a summary of the following Python 3 code
def _apply_loffset(grouper, result):

    needs_offset = (
        isinstance(grouper.loffset, (pd.DateOffset, datetime.timedelta))
        and isinstance(result.index, pd.DatetimeIndex)
        and len(result.index) > 0
    )

    if needs_offset:
        result.index = result.index + grouper.loffset

    grouper.loffset = None

Response: Applies the loffset to the result DataFrame.


Instruction:
How would you implement a function in Python 3 that
iterates over each element in this group

Response:
def _iter_grouped(self):
        """Iterate over each element in this group"""
        for indices in self._group_indices:
            yield self._obj.isel(**{self._group_dim: indices})


Instruction:
Write a Python 3 function that can
restore empty groups if needed.

Response:
def _maybe_restore_empty_groups(self, combined):
        """Our index contained empty groups (e.g., from a resampling). If we
        reduced on that dimension, we want to restore the full index.
        """
        if (self._full_index is not None and
                self._group.name in combined.dims):
            indexers = {self._group.name: self._full_index}
            combined = combined.reindex(**indexers)
        return combined


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _maybe_unstack(self, obj):
        if self._stacked_dim is not None and self._stacked_dim in obj.dims:
            obj = obj.unstack(self._stacked_dim)
            for dim in self._inserted_dims:
                if dim in obj.coords:
                    del obj.coords[dim]
        return obj

Response: Unstacks the array with the specified dimension if there is one.


Instruction:
Implement a function in Python 3 to
return the first element of each group along the group dimension

Response:
def first(self, skipna=None, keep_attrs=None):
        """Return the first element of each group along the group dimension
        """
        return self._first_or_last(duck_array_ops.first, skipna, keep_attrs)


Instruction:
Implement a function in Python 3 to
return the last element of each group along the group dimension

Response:
def last(self, skipna=None, keep_attrs=None):
        """Return the last element of each group along the group dimension
        """
        return self._first_or_last(duck_array_ops.last, skipna, keep_attrs)


Instruction:
Can you implement a function in Python 3 that
fasts version of _iter_grouped that yields Variables without metadata

Response:
def _iter_grouped_shortcut(self):
        """Fast version of `_iter_grouped` that yields Variables without
        metadata
        """
        var = self._obj.variable
        for indices in self._group_indices:
            yield var[{self._group_dim: indices}]


Instruction:
Explain what the following Python 3 code does
def apply(self, func, shortcut=False, args=(), **kwargs):
        if shortcut:
            grouped = self._iter_grouped_shortcut()
        else:
            grouped = self._iter_grouped()
        applied = (maybe_wrap_array(arr, func(arr, *args, **kwargs))
                   for arr in grouped)
        return self._combine(applied, shortcut=shortcut)

Response: Apply a function over each array in the group and concatenate them together into a new array.


Instruction:
Given the following Python 3 function, write the documentation
def _combine(self, applied, shortcut=False):
        applied_example, applied = peek_at(applied)
        coord, dim, positions = self._infer_concat_args(applied_example)
        if shortcut:
            combined = self._concat_shortcut(applied, dim, positions)
        else:
            combined = concat(applied, dim)
            combined = _maybe_reorder(combined, dim, positions)

        if isinstance(combined, type(self._obj)):
            # only restore dimension order for arrays
            combined = self._restore_dim_order(combined)
        if coord is not None:
            if shortcut:
                combined._coords[coord.name] = as_variable(coord)
            else:
                combined.coords[coord.name] = coord
        combined = self._maybe_restore_empty_groups(combined)
        combined = self._maybe_unstack(combined)
        return combined

Response: Recombine the applied objects like the original.


Instruction:
Make a summary of the following Python 3 code
def reduce(self, func, dim=None, axis=None,
               keep_attrs=None, shortcut=True, **kwargs):
        """Reduce the items in this group by applying `func` along some
        dimension(s).

        Parameters
        ----------
        func : function
            Function which can be called in the form
            `func(x, axis=axis, **kwargs)` to return the result of collapsing
            an np.ndarray over an integer valued axis.
        dim : str or sequence of str, optional
            Dimension(s) over which to apply `func`.
        axis : int or sequence of int, optional
            Axis(es) over which to apply `func`. Only one of the 'dimension'
            and 'axis' arguments can be supplied. If neither are supplied, then
            `func` is calculated over all dimension for each group item.
        keep_attrs : bool, optional
            If True, the datasets's attributes (`attrs`) will be copied from
            the original object to the new one.  If False (default), the new
            object will be returned without attributes.
        **kwargs : dict
            Additional keyword arguments passed on to `func`.

        Returns
        -------
        reduced : Array
            Array with summarized data and the indicated dimension(s)
            removed.
        """
        if dim == DEFAULT_DIMS:
            dim = ALL_DIMS
            # TODO change this to dim = self._group_dim after
            # the deprecation process
            if self._obj.ndim > 1:
                warnings.warn(
                    "Default reduction dimension will be changed to the "
                    "grouped dimension in a future version of xarray. To "
                    "silence this warning, pass dim=xarray.ALL_DIMS "
                    "explicitly.",
                    FutureWarning, stacklevel=2)

        if keep_attrs is None:
            keep_attrs = _get_keep_attrs(default=False)

        def reduce_array(ar):
            return ar.reduce(func, dim, axis, keep_attrs=keep_attrs, **kwargs)
        return self.apply(reduce_array, shortcut=shortcut)

Response: Reduce the items in this group by applying func along some dimension and axis.


Instruction:
How would you explain what the following Python 3 function does
def apply(self, func, args=(), **kwargs):
        kwargs.pop('shortcut', None)  # ignore shortcut if set (for now)
        applied = (func(ds, *args, **kwargs) for ds in self._iter_grouped())
        return self._combine(applied)

Response:
Apply a function over each Dataset in the group and concatenate them
        together into a new Dataset.


Instruction:
Write a Python 3 function that can
recombine the applied objects like the original.

Response:
def _combine(self, applied):
        """Recombine the applied objects like the original."""
        applied_example, applied = peek_at(applied)
        coord, dim, positions = self._infer_concat_args(applied_example)
        combined = concat(applied, dim)
        combined = _maybe_reorder(combined, dim, positions)
        if coord is not None:
            combined[coord.name] = coord
        combined = self._maybe_restore_empty_groups(combined)
        combined = self._maybe_unstack(combined)
        return combined


Instruction:
How would you implement a function in Python 3 that
reduces the items in this group by applying func along some dimension.

Response:
def reduce(self, func, dim=None, keep_attrs=None, **kwargs):
        """Reduce the items in this group by applying `func` along some
        dimension(s).

        Parameters
        ----------
        func : function
            Function which can be called in the form
            `func(x, axis=axis, **kwargs)` to return the result of collapsing
            an np.ndarray over an integer valued axis.
        dim : str or sequence of str, optional
            Dimension(s) over which to apply `func`.
        axis : int or sequence of int, optional
            Axis(es) over which to apply `func`. Only one of the 'dimension'
            and 'axis' arguments can be supplied. If neither are supplied, then
            `func` is calculated over all dimension for each group item.
        keep_attrs : bool, optional
            If True, the datasets's attributes (`attrs`) will be copied from
            the original object to the new one.  If False (default), the new
            object will be returned without attributes.
        **kwargs : dict
            Additional keyword arguments passed on to `func`.

        Returns
        -------
        reduced : Array
            Array with summarized data and the indicated dimension(s)
            removed.
        """
        if dim == DEFAULT_DIMS:
            dim = ALL_DIMS
            # TODO change this to dim = self._group_dim after
            # the deprecation process. Do not forget to remove _reduce_method
            warnings.warn(
                "Default reduction dimension will be changed to the "
                "grouped dimension in a future version of xarray. To "
                "silence this warning, pass dim=xarray.ALL_DIMS "
                "explicitly.",
                FutureWarning, stacklevel=2)
        elif dim is None:
            dim = self._group_dim

        if keep_attrs is None:
            keep_attrs = _get_keep_attrs(default=False)

        def reduce_dataset(ds):
            return ds.reduce(func, dim, keep_attrs, **kwargs)
        return self.apply(reduce_dataset)


Instruction:
Can you create a Python 3 function that
returns attrs that are not in ignored_attrs

Response:
def _filter_attrs(attrs, ignored_attrs):
    """ Return attrs that are not in ignored_attrs
    """
    return dict((k, v) for k, v in attrs.items() if k not in ignored_attrs)


Instruction:
Can you generate the documentation for the following Python 3 function
def from_cdms2(variable):
    values = np.asarray(variable)
    name = variable.id
    dims = variable.getAxisIds()
    coords = {}
    for axis in variable.getAxisList():
        coords[axis.id] = DataArray(
            np.asarray(axis), dims=[axis.id],
            attrs=_filter_attrs(axis.attributes, cdms2_ignored_attrs))
    grid = variable.getGrid()
    if grid is not None:
        ids = [a.id for a in grid.getAxisList()]
        for axis in grid.getLongitude(), grid.getLatitude():
            if axis.id not in variable.getAxisIds():
                coords[axis.id] = DataArray(
                    np.asarray(axis[:]), dims=ids,
                    attrs=_filter_attrs(axis.attributes,
                                        cdms2_ignored_attrs))
    attrs = _filter_attrs(variable.attributes, cdms2_ignored_attrs)
    dataarray = DataArray(values, dims=dims, coords=coords, name=name,
                          attrs=attrs)
    return decode_cf(dataarray.to_dataset())[dataarray.name]

Response: Convert a cdms2 variable into a DataArray


Instruction:
Create a Python 3 function for
converting a DataArray into a cdms2 variable and its axes and grids.

Response:
def to_cdms2(dataarray, copy=True):
    """Convert a DataArray into a cdms2 variable
    """
    # we don't want cdms2 to be a hard dependency
    import cdms2

    def set_cdms2_attrs(var, attrs):
        for k, v in attrs.items():
            setattr(var, k, v)

    # 1D axes
    axes = []
    for dim in dataarray.dims:
        coord = encode(dataarray.coords[dim])
        axis = cdms2.createAxis(coord.values, id=dim)
        set_cdms2_attrs(axis, coord.attrs)
        axes.append(axis)

    # Data
    var = encode(dataarray)
    cdms2_var = cdms2.createVariable(var.values, axes=axes, id=dataarray.name,
                                     mask=pd.isnull(var.values), copy=copy)

    # Attributes
    set_cdms2_attrs(cdms2_var, var.attrs)

    # Curvilinear and unstructured grids
    if dataarray.name not in dataarray.coords:

        cdms2_axes = OrderedDict()
        for coord_name in set(dataarray.coords.keys()) - set(dataarray.dims):

            coord_array = dataarray.coords[coord_name].to_cdms2()

            cdms2_axis_cls = (cdms2.coord.TransientAxis2D
                              if coord_array.ndim else
                              cdms2.auxcoord.TransientAuxAxis1D)
            cdms2_axis = cdms2_axis_cls(coord_array)
            if cdms2_axis.isLongitude():
                cdms2_axes['lon'] = cdms2_axis
            elif cdms2_axis.isLatitude():
                cdms2_axes['lat'] = cdms2_axis

        if 'lon' in cdms2_axes and 'lat' in cdms2_axes:
            if len(cdms2_axes['lon'].shape) == 2:
                cdms2_grid = cdms2.hgrid.TransientCurveGrid(
                    cdms2_axes['lat'], cdms2_axes['lon'])
            else:
                cdms2_grid = cdms2.gengrid.AbstractGenericGrid(
                    cdms2_axes['lat'], cdms2_axes['lon'])
            for axis in cdms2_grid.getAxisList():
                cdms2_var.setAxis(cdms2_var.getAxisIds().index(axis.id), axis)
            cdms2_var.setGrid(cdms2_grid)

    return cdms2_var


Instruction:
Write a Python 3 function that can
return attrs with keys in keys list

Response:
def _pick_attrs(attrs, keys):
    """ Return attrs with keys in keys list
    """
    return dict((k, v) for k, v in attrs.items() if k in keys)


Instruction:
Explain what the following Python 3 code does
def _get_iris_args(attrs):
    # iris.unit is deprecated in Iris v1.9
    import cf_units
    args = {'attributes': _filter_attrs(attrs, iris_forbidden_keys)}
    args.update(_pick_attrs(attrs, ('standard_name', 'long_name',)))
    unit_args = _pick_attrs(attrs, ('calendar',))
    if 'units' in attrs:
        args['units'] = cf_units.Unit(attrs['units'], **unit_args)
    return args

Response: Converts the xarray attrs into args that can be passed into Iris


Instruction:
Here you have a function in Python 3, explain what it does
def to_iris(dataarray):
    # Iris not a hard dependency
    import iris
    from iris.fileformats.netcdf import parse_cell_methods

    dim_coords = []
    aux_coords = []

    for coord_name in dataarray.coords:
        coord = encode(dataarray.coords[coord_name])
        coord_args = _get_iris_args(coord.attrs)
        coord_args['var_name'] = coord_name
        axis = None
        if coord.dims:
            axis = dataarray.get_axis_num(coord.dims)
        if coord_name in dataarray.dims:
            try:
                iris_coord = iris.coords.DimCoord(coord.values, **coord_args)
                dim_coords.append((iris_coord, axis))
            except ValueError:
                iris_coord = iris.coords.AuxCoord(coord.values, **coord_args)
                aux_coords.append((iris_coord, axis))
        else:
            iris_coord = iris.coords.AuxCoord(coord.values, **coord_args)
            aux_coords.append((iris_coord, axis))

    args = _get_iris_args(dataarray.attrs)
    args['var_name'] = dataarray.name
    args['dim_coords_and_dims'] = dim_coords
    args['aux_coords_and_dims'] = aux_coords
    if 'cell_methods' in dataarray.attrs:
        args['cell_methods'] = \
            parse_cell_methods(dataarray.attrs['cell_methods'])

    masked_data = duck_array_ops.masked_invalid(dataarray.data)
    cube = iris.cube.Cube(masked_data, **args)

    return cube

Response: Convert a DataArray into a Iris Cube


Instruction:
Here you have a function in Python 3, explain what it does
def _iris_obj_to_attrs(obj):
    attrs = {'standard_name': obj.standard_name,
             'long_name': obj.long_name}
    if obj.units.calendar:
        attrs['calendar'] = obj.units.calendar
    if obj.units.origin != '1' and not obj.units.is_unknown():
        attrs['units'] = obj.units.origin
    attrs.update(obj.attributes)
    return dict((k, v) for k, v in attrs.items() if v is not None)

Response: Return a dictionary of attrs when given a Iris object


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _iris_cell_methods_to_str(cell_methods_obj):
    cell_methods = []
    for cell_method in cell_methods_obj:
        names = ''.join(['{}: '.format(n) for n in cell_method.coord_names])
        intervals = ' '.join(['interval: {}'.format(interval)
                              for interval in cell_method.intervals])
        comments = ' '.join(['comment: {}'.format(comment)
                             for comment in cell_method.comments])
        extra = ' '.join([intervals, comments]).strip()
        if extra:
            extra = ' ({})'.format(extra)
        cell_methods.append(names + cell_method.method + extra)
    return ' '.join(cell_methods)

Response: Converts a Iris cell methods into a string


Instruction:
Can you tell what is the following Python 3 function doing
def _name(iris_obj, default='unknown'):
    return (iris_obj.var_name or iris_obj.standard_name or
            iris_obj.long_name or default)

Response: Mimicks name method but with different name resolution order.