Skip to content
Merged
7 changes: 5 additions & 2 deletions xarray/backends/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1463,7 +1463,7 @@ def open_mfdataset(
"netcdf4" over "h5netcdf" over "scipy" (customizable via
``netcdf_engine_order`` in ``xarray.set_options()``). A custom backend
class (a subclass of ``BackendEntrypoint``) can also be used.
data_vars : {"minimal", "different", "all"} or list of str, default: "all"
data_vars : {"minimal", "different", "all", None} or list of str, default: "all"
These data variables will be concatenated together:
* "minimal": Only data variables in which the dimension already
appears are included.
Expand All @@ -1473,9 +1473,12 @@ class (a subclass of ``BackendEntrypoint``) can also be used.
load the data payload of data variables into memory if they are not
already loaded.
* "all": All data variables will be concatenated.
* None: Means ``"all"`` if ``concat_dim`` is not present in any of
the ``objs``, and ``"minimal"`` if ``concat_dim`` is present
in any of ``objs``.
* list of str: The listed data variables will be concatenated, in
addition to the "minimal" data variables.
coords : {"minimal", "different", "all"} or list of str, optional
coords : {"minimal", "different", "all"} or list of str, default: "different"
These coordinate variables will be concatenated together:
* "minimal": Only coordinates in which the dimension already appears
are included.
Expand Down
49 changes: 33 additions & 16 deletions xarray/structure/combine.py
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ def combine_nested(
Must be the same length as the depth of the list passed to
``datasets``.
compat : {"identical", "equals", "broadcast_equals", \
"no_conflicts", "override"}, optional
"no_conflicts", "override"}, default: "no_conflicts"
String indicating how to compare variables of the same name for
potential merge conflicts:

Expand All @@ -522,7 +522,7 @@ def combine_nested(
must be equal. The returned dataset then contains the combination
of all non-null values.
- "override": skip comparing and pick variable from first dataset
data_vars : {"minimal", "different", "all" or list of str}, optional
data_vars : {"minimal", "different", "all", None} or list of str, default: "all"
These data variables will be concatenated together:
* "minimal": Only data variables in which the dimension already
appears are included.
Expand All @@ -532,15 +532,16 @@ def combine_nested(
load the data payload of data variables into memory if they are not
already loaded.
* "all": All data variables will be concatenated.
* None: Means ``"all"`` if ``dim`` is not present in any of the ``objs``,
and ``"minimal"`` if ``dim`` is present in any of ``objs``.
* list of dims: The listed data variables will be concatenated, in
* None: Means ``"all"`` if ``concat_dim`` is not present in any of
the ``objs``, and ``"minimal"`` if ``concat_dim`` is present
in any of ``objs``.
* list of str: The listed data variables will be concatenated, in
addition to the "minimal" data variables.

coords : {"minimal", "different", "all" or list of str}, optional
coords : {"minimal", "different", "all"} or list of str, default: "different"
These coordinate variables will be concatenated together:
* "minimal": Only coordinates in which the dimension already appears
are included. If concatenating over a dimension _not_
* "minimal": Only coordinates in which the dimension already
appears are included. If concatenating over a dimension _not_
present in any of the objects, then all data variables will
be concatenated along that new dimension.
* "different": Coordinates which are not equal (ignoring attributes)
Expand All @@ -550,14 +551,14 @@ def combine_nested(
loaded.
* "all": All coordinate variables will be concatenated, except
those corresponding to other dimensions.
* list of Hashable: The listed coordinate variables will be concatenated,
* list of str: The listed coordinate variables will be concatenated,
in addition to the "minimal" coordinates.

fill_value : scalar or dict-like, optional
Value to use for newly missing values. If a dict-like, maps
variable names to fill values. Use a data array's name to
refer to its values.
join : {"outer", "inner", "left", "right", "exact"}, optional
join : {"outer", "inner", "left", "right", "exact"}, default: "outer"
String indicating how to combine differing indexes
(excluding concat_dim) in objects

Expand Down Expand Up @@ -836,7 +837,8 @@ def combine_by_coords(
data_objects : Iterable of Datasets or DataArrays
Data objects to combine.

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

Expand All @@ -850,7 +852,7 @@ def combine_by_coords(
of all non-null values.
- "override": skip comparing and pick variable from first dataset

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

- "minimal": Only data variables in which the dimension already
Expand All @@ -861,18 +863,33 @@ def combine_by_coords(
load the data payload of data variables into memory if they are not
already loaded.
- "all": All data variables will be concatenated.
- None: Means ``"all"`` if ``concat_dim`` is not present in any of
the ``objs``, and ``"minimal"`` if ``concat_dim`` is present
in any of ``objs``.
- list of str: The listed data variables will be concatenated, in
addition to the "minimal" data variables.
coords : {"minimal", "different", "all"} or list of str, default: "different"
These coordinate variables will be concatenated together:

If objects are DataArrays, `data_vars` must be "all".
coords : {"minimal", "different", "all"} or list of str, optional
As per the "data_vars" kwarg, but for coordinate variables.
- "minimal": Only coordinates in which the dimension already
appears are included. If concatenating over a dimension _not_
present in any of the objects, then all data variables will
be concatenated along that new dimension.
- "different": Coordinates which are not equal (ignoring attributes)
across all datasets are also concatenated (as well as all for which
dimension already appears). Beware: this option may load the data
payload of coordinate variables into memory if they are not already
loaded.
- "all": All coordinate variables will be concatenated, except
those corresponding to other dimensions.
- list of str: The listed coordinate variables will be concatenated,
in addition to the "minimal" coordinates.
fill_value : scalar or dict-like, optional
Value to use for newly missing values. If a dict-like, maps
variable names to fill values. Use a data array's name to
refer to its values. If None, raises a ValueError if
the passed Datasets do not create a complete hypercube.
join : {"outer", "inner", "left", "right", "exact"}, optional
join : {"outer", "inner", "left", "right", "exact"}, default: "outer"
String indicating how to combine differing indexes in objects

- "outer": use the union of object indexes
Expand Down
15 changes: 8 additions & 7 deletions xarray/structure/concat.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def concat(
unchanged. If dimension is provided as a Variable, DataArray or Index, its name
is used as the dimension to concatenate along and the values are added
as a coordinate.
data_vars : {"minimal", "different", "all", None} or list of Hashable, optional
data_vars : {"minimal", "different", "all", None} or list of str, default: "all"
These data variables will be concatenated together:
* "minimal": Only data variables in which the dimension already
appears are included.
Expand All @@ -126,11 +126,11 @@ def concat(
* "all": All data variables will be concatenated.
* None: Means ``"all"`` if ``dim`` is not present in any of the ``objs``,
and ``"minimal"`` if ``dim`` is present in any of ``objs``.
* list of dims: The listed data variables will be concatenated, in
* list of str: The listed data variables will be concatenated, in
addition to the "minimal" data variables.

If objects are DataArrays, data_vars must be "all".
coords : {"minimal", "different", "all"} or list of Hashable, optional
If objects are DataArrays, data_vars must be "all" or None.
coords : {"minimal", "different", "all"} or list of str, default: "different"
These coordinate variables will be concatenated together:
* "minimal": Only coordinates in which the dimension already appears
are included.
Expand All @@ -141,9 +141,10 @@ def concat(
loaded.
* "all": All coordinate variables will be concatenated, except
those corresponding to other dimensions.
* list of Hashable: The listed coordinate variables will be concatenated,
* list of str: The listed coordinate variables will be concatenated,
in addition to the "minimal" coordinates.
compat : {"identical", "equals", "broadcast_equals", "no_conflicts", "override"}, optional
compat : {"identical", "equals", "broadcast_equals", "no_conflicts", "override"}, \
default: "equals"
String indicating how to compare non-concatenated variables of the same name for
potential conflicts. This is passed down to merge.

Expand All @@ -164,7 +165,7 @@ def concat(
Value to use for newly missing values. If a dict-like, maps
variable names to fill values. Use a data array's name to
refer to its values.
join : {"outer", "inner", "left", "right", "exact"}, optional
join : {"outer", "inner", "left", "right", "exact"}, default: "outer"
String indicating how to combine differing indexes
(excluding dim) in objects

Expand Down
17 changes: 15 additions & 2 deletions xarray/tests/test_concat.py
Original file line number Diff line number Diff line change
Expand Up @@ -979,8 +979,12 @@ def test_concat_do_not_promote(self) -> None:
Dataset({"y": ("t", [1])}, {"x": 1, "t": [0]}),
Dataset({"y": ("t", [2])}, {"x": 2, "t": [0]}),
]
with pytest.raises(ValueError):
concat(objs, "t", coords="minimal")
with set_options(use_new_combine_kwarg_defaults=False):
with pytest.raises(ValueError):
concat(objs, "t", coords="minimal")
with set_options(use_new_combine_kwarg_defaults=True):
with pytest.raises(ValueError):
concat(objs, "t", compat="equals")

def test_concat_dim_is_variable(self) -> None:
objs = [Dataset({"x": 0}), Dataset({"x": 1})]
Expand Down Expand Up @@ -1664,8 +1668,17 @@ def test_concat_datatree_along_existing_dim_defaults(self):
FutureWarning, match="will change from data_vars='all' to data_vars=None"
):
actual = concat([dt1, dt2], dim="x")

assert actual.identical(expected)

with set_options(use_new_combine_kwarg_defaults=True):
expected = DataTree.from_dict(
data={"/a": ("x", [1, 2]), "/b": 3}, coords={"/x": [0, 1]}
)
actual = concat([dt1, dt2], dim="x")

assert actual.identical(expected)

def test_concat_datatree_isomorphic_error(self):
dt1 = DataTree.from_dict(data={"/data": ("x", [1]), "/a": None})
dt2 = DataTree.from_dict(data={"/data": ("x", [2]), "/b": None})
Expand Down
11 changes: 10 additions & 1 deletion xarray/tests/test_dask.py
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,16 @@ def test_concat_loads_variables(self):
assert isinstance(out["d"].data, dask.array.Array)
assert isinstance(out["c"].data, dask.array.Array)

out = xr.concat([ds1, ds2, ds3], dim="n", data_vars=[], coords=[])
with xr.set_options(use_new_combine_kwarg_defaults=True):
out = xr.concat([ds1, ds2, ds3], dim="n", data_vars=[], coords=[])
# no extra kernel calls
assert kernel_call_count == 6
assert isinstance(out["d"].data, dask.array.Array)
assert isinstance(out["c"].data, dask.array.Array)

out = xr.concat(
[ds1, ds2, ds3], dim="n", data_vars=[], coords=[], compat="equals"
)
# variables are loaded once as we are validating that they're identical
assert kernel_call_count == 12
assert isinstance(out["d"].data, np.ndarray)
Expand Down
6 changes: 3 additions & 3 deletions xarray/tests/test_merge.py
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,7 @@ def test_merge_coordinates(self):
def test_merge_error(self):
ds = xr.Dataset({"x": 0})
with pytest.raises(xr.MergeError):
xr.merge([ds, ds + 1])
xr.merge([ds, ds + 1], compat="no_conflicts")

def test_merge_alignment_error(self):
ds = xr.Dataset(coords={"x": [1, 2]})
Expand Down Expand Up @@ -624,7 +624,7 @@ def test_merge(self):
assert_identical(data, actual)

with pytest.raises(ValueError, match="conflicting values for variable"):
ds1.merge(ds2.rename({"var3": "var1"}))
ds1.merge(ds2.rename({"var3": "var1"}), compat="no_conflicts")
with pytest.raises(ValueError, match=r"should be coordinates or not"):
data.reset_coords().merge(data)
with pytest.raises(ValueError, match=r"should be coordinates or not"):
Expand Down Expand Up @@ -948,7 +948,7 @@ def test_merge_error_includes_path(self) -> None:
"Raised whilst mapping function over node(s) with path 'a'"
),
):
xr.merge([tree1, tree2], join="exact")
xr.merge([tree1, tree2], join="exact", compat="no_conflicts")

def test_fill_value_errors(self) -> None:
trees = [xr.DataTree(), xr.DataTree()]
Expand Down
42 changes: 12 additions & 30 deletions xarray/tests/test_units.py
Original file line number Diff line number Diff line change
Expand Up @@ -785,7 +785,7 @@ def test_combine_by_coords(variant, unit, error, dtype):

if error is not None:
with pytest.raises(error):
xr.combine_by_coords([ds, other])
xr.combine_by_coords([ds, other], coords="different", compat="no_conflicts")

return

Expand Down Expand Up @@ -825,12 +825,6 @@ def test_combine_by_coords(variant, unit, error, dtype):
"coords",
),
)
@pytest.mark.filterwarnings(
"ignore:.*the default value for join will change:FutureWarning"
)
@pytest.mark.filterwarnings(
"ignore:.*the default value for compat will change:FutureWarning"
)
def test_combine_nested(variant, unit, error, dtype):
original_unit = unit_registry.m

Expand Down Expand Up @@ -890,7 +884,7 @@ def test_combine_nested(variant, unit, error, dtype):
},
)

func = function(xr.combine_nested, concat_dim=["x", "y"])
func = function(xr.combine_nested, concat_dim=["x", "y"], join="outer")
if error is not None:
with pytest.raises(error):
func([[ds1, ds2], [ds3, ds4]])
Expand Down Expand Up @@ -1071,12 +1065,6 @@ def test_concat_dataset(variant, unit, error, dtype):
"coords",
),
)
@pytest.mark.filterwarnings(
"ignore:.*the default value for join will change:FutureWarning"
)
@pytest.mark.filterwarnings(
"ignore:.*the default value for compat will change:FutureWarning"
)
def test_merge_dataarray(variant, unit, error, dtype):
original_unit = unit_registry.m

Expand Down Expand Up @@ -1128,9 +1116,10 @@ def test_merge_dataarray(variant, unit, error, dtype):
dims=("y", "z"),
)

func = function(xr.merge, compat="no_conflicts", join="outer")
if error is not None:
with pytest.raises(error):
xr.merge([arr1, arr2, arr3])
func([arr1, arr2, arr3])

return

Expand All @@ -1146,13 +1135,13 @@ def test_merge_dataarray(variant, unit, error, dtype):
convert_and_strip = lambda arr: strip_units(convert_units(arr, units))

expected = attach_units(
xr.merge(
func(
[convert_and_strip(arr1), convert_and_strip(arr2), convert_and_strip(arr3)]
),
units,
)

actual = xr.merge([arr1, arr2, arr3])
actual = func([arr1, arr2, arr3])

assert_units_equal(expected, actual)
assert_allclose(expected, actual)
Expand Down Expand Up @@ -1181,12 +1170,6 @@ def test_merge_dataarray(variant, unit, error, dtype):
"coords",
),
)
@pytest.mark.filterwarnings(
"ignore:.*the default value for join will change:FutureWarning"
)
@pytest.mark.filterwarnings(
"ignore:.*the default value for compat will change:FutureWarning"
)
def test_merge_dataset(variant, unit, error, dtype):
original_unit = unit_registry.m

Expand Down Expand Up @@ -1235,7 +1218,7 @@ def test_merge_dataset(variant, unit, error, dtype):
},
)

func = function(xr.merge)
func = function(xr.merge, compat="no_conflicts", join="outer")
if error is not None:
with pytest.raises(error):
func([ds1, ds2, ds3])
Expand Down Expand Up @@ -5607,9 +5590,6 @@ def test_content_manipulation(self, func, variant, dtype):
"coords",
),
)
@pytest.mark.filterwarnings(
"ignore:.*the default value for join will change:FutureWarning"
)
@pytest.mark.filterwarnings(
"ignore:.*the default value for compat will change:FutureWarning"
)
Expand Down Expand Up @@ -5651,13 +5631,15 @@ def test_merge(self, variant, unit, error, dtype):

if error is not None:
with pytest.raises(error):
left.merge(right)
left.merge(right, compat="no_conflicts", join="outer")

return

converted = convert_units(right, units)
expected = attach_units(strip_units(left).merge(strip_units(converted)), units)
actual = left.merge(right)
expected = attach_units(
strip_units(left).merge(strip_units(converted), join="outer"), units
)
actual = left.merge(right, join="outer")

assert_units_equal(expected, actual)
assert_equal(expected, actual)
Expand Down
Loading