Skip to content

Dataset.broadcast_like(other) should broadcast against like variables in other #6549

Open

Description

@headtr1ck

Is your feature request related to a problem?

I am a bit puzzled about how xarrays is broadcasting Datasets.
It seems to always add all dimensions to all variables.
Is this what you want in general?

See this example:

import xarray as xr

da = xr.DataArray([[1, 2, 3]], dims=("x", "y"))
# <xarray.DataArray (x: 1, y: 3)>
# array([[1, 2, 3]])
ds = xr.Dataset({"a": ("x", [1]), "b": ("z", [2, 3])})
# <xarray.Dataset>
# Dimensions:  (x: 1, z: 2)
# Dimensions without coordinates: x, z
# Data variables:
#     a        (x) int32 1
#     b        (z) int32 2 3
ds.broadcast_like(da)

# returns:
# <xarray.Dataset>
# Dimensions:  (x: 1, y: 3, z: 2)
# Dimensions without coordinates: x, y, z
# Data variables:
#     a        (x, y, z) int32 1 1 1 1 1 1
#     b        (x, y, z) int32 2 3 2 3 2 3

# I think it should return:
# <xarray.Dataset>
# Dimensions:  (x: 1, y: 3, z: 2)
# Dimensions without coordinates: x, y, z
# Data variables:
#     a        (x, y) int32 1 1 1  # notice here without "z" dim
#     b        (x, y, z) int32 2 3 2 3 2 3

Describe the solution you'd like

I would like broadcasting to behave the same way as e.g. a simple addition.
In the upper example da + ds produces the dimensions that I want.

Describe alternatives you've considered

ds + xr.zeros_like(da) this works, but seems more like a "dirty hack".

Additional context

Maybe one can add an option to broadcasting that controls this behavior?

Activity

  1. keewis commented on Apr 30, 2022

    @keewis
    Collaborator

    see also #6304 which covers xr.broadcast

  2. headtr1ck commented on Apr 30, 2022

    @headtr1ck
    CollaboratorAuthor

    see also #6304 which covers xr.broadcast

    I tried adding a join input to Dataset.broadcast_like and passing it to align, but that did not work (at least for join="inner"). Still got the same result...

  3. headtr1ck commented on May 1, 2022

    @headtr1ck
    CollaboratorAuthor

    related to #6227

  4. changed the title [-]Improved Dataset broadcasting[/-] [+]Add a broadcasting mode that inserts size-1 labeled dimensions[/+] on Feb 6, 2025
  5. changed the title [-]Add a broadcasting mode that inserts size-1 labeled dimensions[/-] [+]Add a broadcasting mode that inserts size-1 unlabeled dimension[/+] on Feb 6, 2025
  6. changed the title [-]Add a broadcasting mode that inserts size-1 unlabeled dimension[/-] [+]Improved Dataset.broadcasting[/+] on Feb 6, 2025
  7. dcherian commented on Feb 6, 2025

    @dcherian
    Contributor

    I keep misunderstanding this issue so typing this out to make sure I got it right.

    Writing out dimension names in square brackets

    ds['a': 'x', 'b': 'z'].broadcast_like(da: ['x', 'y']) -> ds['a': ['x', y'], 'b': ['x', 'y', 'z']]

    IIUC the request is to avoid broadcasting the variables in ds against each other, and to only broadcast each variable against da separately. Did I get it right?

  8. changed the title [-]Improved Dataset.broadcasting[/-] [+]`Dataset.broadcast_like(other)` should broadcast against like variables in other[/+] on Feb 6, 2025
  9. dcherian commented on Feb 6, 2025

    @dcherian
    Contributor

    @mjwillson posted a nice summary in #10031 :

    I had to summarize the overall problem, it's that behaviour of xarray.broadcast (and Dataset.broadcast_like etc) is not consistent with how actual arithmetic operations broadcast, in cases where Datasets are involved.

  10. alvarosg commented on Feb 6, 2025

    @alvarosg

    In the light of #10031, and broadcasting a dataset to itself not behaving as a no-op, should we label this as "bug" rather than "enhancement"?

  11. headtr1ck commented on Oct 27, 2025

    @headtr1ck
    CollaboratorAuthor

    I found a use-case for broadcasting a dataset like requested: When trying to change values in-place, this only works if the replacement values are already broadcasted.
    An example can be found here: https://github.com/pydata/xarray/blob/main/xarray/computation/computation.py#L842 where instead of broadcasting I had to resort to adding a zero-valued dataset.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions