Skip to content

Specialization of set_dims for new dimensions of length 1 #9462

Closed
@hmaarrfk

Description

@hmaarrfk

Is your feature request related to a problem?

Our duck arrays got caught by duck_array_ops.broadcast_to

expanded_data = duck_array_ops.broadcast_to(self.data, tmp_shape)

really boiling down to np.broadcast_to since we don't implement it quite yet.

In the lines above, there seems to be a desire to keep the array "writable" (that won't work in our arrays, they are read-only anyway), but there is an other case where the underlying array stays writable, and that is when new dimensions of "1" get added.

Describe the solution you'd like

New dimensions of 1 to be inserted via slicing np.newaxis

I thinke the code could be refactored to be

       new_dims = tuple(d for d in dim if d not in self_dims)
       expanded_dims = new_dims + self.dims

       if self.dims == expanded_dims:
            # don't use broadcast_to unless necessary so the result remains
            # writeable if possible
            expanded_data = self.data
       elif shape is None or all(shape[d] == 1for d in new_dims):
            # don't use broadcast_to unless necessary so the result remains
            # writeable if possible
            # especially when creating dimensions of size 1
            indexer = (None,) * (len(expanded_dims) - self.ndim) + (...,)
            expanded_data = self.data[indexer]
       else:
            dims_map = dict(zip(dim, shape))
            tmp_shape = tuple(dims_map[d] for d in expanded_dims)
            expanded_data = duck_array_ops.broadcast_to(self.data, tmp_shape)

effectively just flipping the "else" and and the "elif"

Describe alternatives you've considered

Manually broadcasting the DataArrays prior to the call to xr.expand_dims

Additional context

import numpy as np
a = np.zeros((3, 2))
a[np.newaxis, :, np.newaxis, :, np.newaxis, ...].flags.writeable
assert a[np.newaxis, :, np.newaxis, :, np.newaxis, ...].flags.writeable

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions