@@ -2853,6 +2853,7 @@ def interp(
2853
2853
method : str = "linear" ,
2854
2854
assume_sorted : bool = False ,
2855
2855
kwargs : Mapping [str , Any ] = None ,
2856
+ method_non_numeric : str = "nearest" ,
2856
2857
** coords_kwargs : Any ,
2857
2858
) -> "Dataset" :
2858
2859
"""Multidimensional interpolation of Dataset.
@@ -2877,6 +2878,9 @@ def interp(
2877
2878
Additional keyword arguments passed to scipy's interpolator. Valid
2878
2879
options and their behavior depend on if 1-dimensional or
2879
2880
multi-dimensional interpolation is used.
2881
+ method_non_numeric : {"nearest", "pad", "ffill", "backfill", "bfill"}, optional
2882
+ Method for non-numeric types. Passed on to :py:meth:`Dataset.reindex`.
2883
+ ``"nearest"`` is used by default.
2880
2884
**coords_kwargs : {dim: coordinate, ...}, optional
2881
2885
The keyword arguments form of ``coords``.
2882
2886
One of coords or coords_kwargs must be provided.
@@ -3034,6 +3038,7 @@ def _validate_interp_indexer(x, new_x):
3034
3038
}
3035
3039
3036
3040
variables : Dict [Hashable , Variable ] = {}
3041
+ to_reindex : Dict [Hashable , Variable ] = {}
3037
3042
for name , var in obj ._variables .items ():
3038
3043
if name in indexers :
3039
3044
continue
@@ -3043,20 +3048,45 @@ def _validate_interp_indexer(x, new_x):
3043
3048
else :
3044
3049
use_indexers = validated_indexers
3045
3050
3046
- if var .dtype .kind in "uifc" :
3051
+ dtype_kind = var .dtype .kind
3052
+ if dtype_kind in "uifc" :
3053
+ # For normal number types do the interpolation:
3047
3054
var_indexers = {k : v for k , v in use_indexers .items () if k in var .dims }
3048
3055
variables [name ] = missing .interp (var , var_indexers , method , ** kwargs )
3056
+ elif dtype_kind in "ObU" and (use_indexers .keys () & var .dims ):
3057
+ # For types that we do not understand do stepwise
3058
+ # interpolation to avoid modifying the elements.
3059
+ # Use reindex_variables instead because it supports
3060
+ # booleans and objects and retains the dtype but inside
3061
+ # this loop there might be some duplicate code that slows it
3062
+ # down, therefore collect these signals and run it later:
3063
+ to_reindex [name ] = var
3049
3064
elif all (d not in indexers for d in var .dims ):
3050
- # keep unrelated object array
3065
+ # For anything else we can only keep variables if they
3066
+ # are not dependent on any coords that are being
3067
+ # interpolated along:
3051
3068
variables [name ] = var
3052
3069
3070
+ if to_reindex :
3071
+ # Reindex variables:
3072
+ variables_reindex = alignment .reindex_variables (
3073
+ variables = to_reindex ,
3074
+ sizes = obj .sizes ,
3075
+ indexes = obj .xindexes ,
3076
+ indexers = {k : v [- 1 ] for k , v in validated_indexers .items ()},
3077
+ method = method_non_numeric ,
3078
+ )[0 ]
3079
+ variables .update (variables_reindex )
3080
+
3081
+ # Get the coords that also exist in the variables:
3053
3082
coord_names = obj ._coord_names & variables .keys ()
3083
+ # Get the indexes that are not being interpolated along:
3054
3084
indexes = {k : v for k , v in obj .xindexes .items () if k not in indexers }
3055
3085
selected = self ._replace_with_new_dims (
3056
3086
variables .copy (), coord_names , indexes = indexes
3057
3087
)
3058
3088
3059
- # attach indexer as coordinate
3089
+ # Attach indexer as coordinate
3060
3090
variables .update (indexers )
3061
3091
for k , v in indexers .items ():
3062
3092
assert isinstance (v , Variable )
@@ -3077,6 +3107,7 @@ def interp_like(
3077
3107
method : str = "linear" ,
3078
3108
assume_sorted : bool = False ,
3079
3109
kwargs : Mapping [str , Any ] = None ,
3110
+ method_non_numeric : str = "nearest" ,
3080
3111
) -> "Dataset" :
3081
3112
"""Interpolate this object onto the coordinates of another object,
3082
3113
filling the out of range values with NaN.
@@ -3098,6 +3129,9 @@ def interp_like(
3098
3129
values.
3099
3130
kwargs : dict, optional
3100
3131
Additional keyword passed to scipy's interpolator.
3132
+ method_non_numeric : {"nearest", "pad", "ffill", "backfill", "bfill"}, optional
3133
+ Method for non-numeric types. Passed on to :py:meth:`Dataset.reindex`.
3134
+ ``"nearest"`` is used by default.
3101
3135
3102
3136
Returns
3103
3137
-------
@@ -3133,7 +3167,13 @@ def interp_like(
3133
3167
# We do not support interpolation along object coordinate.
3134
3168
# reindex instead.
3135
3169
ds = self .reindex (object_coords )
3136
- return ds .interp (numeric_coords , method , assume_sorted , kwargs )
3170
+ return ds .interp (
3171
+ coords = numeric_coords ,
3172
+ method = method ,
3173
+ assume_sorted = assume_sorted ,
3174
+ kwargs = kwargs ,
3175
+ method_non_numeric = method_non_numeric ,
3176
+ )
3137
3177
3138
3178
# Helper methods for rename()
3139
3179
def _rename_vars (self , name_dict , dims_dict ):
0 commit comments