Apply common operations for idxmin and idxmax.
(
*,
array,
func: Callable,
dim: Hashable | None = None,
skipna: bool | None = None,
fill_value: Any = dtypes.NA,
keep_attrs: bool | None = None,
)
| 958 | |
| 959 | |
| 960 | def _calc_idxminmax( |
| 961 | *, |
| 962 | array, |
| 963 | func: Callable, |
| 964 | dim: Hashable | None = None, |
| 965 | skipna: bool | None = None, |
| 966 | fill_value: Any = dtypes.NA, |
| 967 | keep_attrs: bool | None = None, |
| 968 | ): |
| 969 | """Apply common operations for idxmin and idxmax.""" |
| 970 | # This function doesn't make sense for scalars so don't try |
| 971 | if not array.ndim: |
| 972 | raise ValueError("This function does not apply for scalars") |
| 973 | |
| 974 | if dim is not None: |
| 975 | pass # Use the dim if available |
| 976 | elif array.ndim == 1: |
| 977 | # it is okay to guess the dim if there is only 1 |
| 978 | dim = array.dims[0] |
| 979 | else: |
| 980 | # The dim is not specified and ambiguous. Don't guess. |
| 981 | raise ValueError("Must supply 'dim' argument for multidimensional arrays") |
| 982 | |
| 983 | if dim not in array.dims: |
| 984 | raise KeyError( |
| 985 | f"Dimension {dim!r} not found in array dimensions {array.dims!r}" |
| 986 | ) |
| 987 | if dim not in array.coords: |
| 988 | raise KeyError( |
| 989 | f"Dimension {dim!r} is not one of the coordinates {tuple(array.coords.keys())}" |
| 990 | ) |
| 991 | |
| 992 | # These are dtypes with NaN values argmin and argmax can handle |
| 993 | na_dtypes = "cfO" |
| 994 | |
| 995 | if skipna or (skipna is None and array.dtype.kind in na_dtypes): |
| 996 | # Need to skip NaN values since argmin and argmax can't handle them |
| 997 | allna = array.isnull().all(dim) |
| 998 | array = array.where(~allna, 0) |
| 999 | |
| 1000 | # This will run argmin or argmax. |
| 1001 | index = func(array, dim=dim, axis=None, keep_attrs=keep_attrs, skipna=skipna) |
| 1002 | |
| 1003 | # Handle chunked arrays (e.g. dask). |
| 1004 | coord = array[dim]._variable.to_base_variable() |
| 1005 | if is_chunked_array(array.data): |
| 1006 | chunkmanager = get_chunked_array_type(array.data) |
| 1007 | coord_array = chunkmanager.from_array( |
| 1008 | array[dim].data, chunks=((array.sizes[dim],),) |
| 1009 | ) |
| 1010 | coord = coord.copy(data=coord_array) |
| 1011 | else: |
| 1012 | coord = coord.copy(data=to_like_array(array[dim].data, array.data)) |
| 1013 | |
| 1014 | res = index._replace(coord[(index.variable,)]).rename(dim) |
| 1015 | |
| 1016 | if skipna or (skipna is None and array.dtype.kind in na_dtypes): |
| 1017 | # Put the NaN values back in after removing them |
nothing calls this directly
no test coverage detected
searching dependent graphs…