@@ -1737,8 +1737,8 @@ def maybe_chunk(name, var, chunks):
1737
1737
return self ._replace (variables )
1738
1738
1739
1739
def _validate_indexers (
1740
- self , indexers : Mapping
1741
- ) -> List [Tuple [Any , Union [slice , Variable ]]]:
1740
+ self , indexers : Mapping [ Hashable , Any ]
1741
+ ) -> Iterator [Tuple [Hashable , Union [int , slice , np . ndarray , Variable ]]]:
1742
1742
""" Here we make sure
1743
1743
+ indexer has a valid keys
1744
1744
+ indexer is in a valid data type
@@ -1747,50 +1747,61 @@ def _validate_indexers(
1747
1747
"""
1748
1748
from .dataarray import DataArray
1749
1749
1750
- invalid = [ k for k in indexers if k not in self .dims ]
1750
+ invalid = indexers . keys () - self .dims . keys ()
1751
1751
if invalid :
1752
1752
raise ValueError ("dimensions %r do not exist" % invalid )
1753
1753
1754
1754
# all indexers should be int, slice, np.ndarrays, or Variable
1755
- indexers_list : List [Tuple [Any , Union [slice , Variable ]]] = []
1756
1755
for k , v in indexers .items ():
1757
- if isinstance (v , slice ):
1758
- indexers_list .append ((k , v ))
1759
- continue
1760
-
1761
- if isinstance (v , Variable ):
1762
- pass
1756
+ if isinstance (v , (int , slice , Variable )):
1757
+ yield k , v
1763
1758
elif isinstance (v , DataArray ):
1764
- v = v .variable
1759
+ yield k , v .variable
1765
1760
elif isinstance (v , tuple ):
1766
- v = as_variable (v )
1761
+ yield k , as_variable (v )
1767
1762
elif isinstance (v , Dataset ):
1768
1763
raise TypeError ("cannot use a Dataset as an indexer" )
1769
1764
elif isinstance (v , Sequence ) and len (v ) == 0 :
1770
- v = Variable (( k ,), np .zeros ((0 ,), dtype = "int64" ) )
1765
+ yield k , np .empty ((0 ,), dtype = "int64" )
1771
1766
else :
1772
1767
v = np .asarray (v )
1773
1768
1774
- if v .dtype .kind == "U" or v . dtype . kind == "S " :
1769
+ if v .dtype .kind in "US " :
1775
1770
index = self .indexes [k ]
1776
1771
if isinstance (index , pd .DatetimeIndex ):
1777
1772
v = v .astype ("datetime64[ns]" )
1778
1773
elif isinstance (index , xr .CFTimeIndex ):
1779
1774
v = _parse_array_of_cftime_strings (v , index .date_type )
1780
1775
1781
- if v .ndim == 0 :
1782
- v = Variable ((), v )
1783
- elif v .ndim == 1 :
1784
- v = Variable ((k ,), v )
1785
- else :
1776
+ if v .ndim > 1 :
1786
1777
raise IndexError (
1787
1778
"Unlabeled multi-dimensional array cannot be "
1788
1779
"used for indexing: {}" .format (k )
1789
1780
)
1781
+ yield k , v
1790
1782
1791
- indexers_list .append ((k , v ))
1792
-
1793
- return indexers_list
1783
+ def _validate_interp_indexers (
1784
+ self , indexers : Mapping [Hashable , Any ]
1785
+ ) -> Iterator [Tuple [Hashable , Variable ]]:
1786
+ """Variant of _validate_indexers to be used for interpolation
1787
+ """
1788
+ for k , v in self ._validate_indexers (indexers ):
1789
+ if isinstance (v , Variable ):
1790
+ if v .ndim == 1 :
1791
+ yield k , v .to_index_variable ()
1792
+ else :
1793
+ yield k , v
1794
+ elif isinstance (v , int ):
1795
+ yield k , Variable ((), v )
1796
+ elif isinstance (v , np .ndarray ):
1797
+ if v .ndim == 0 :
1798
+ yield k , Variable ((), v )
1799
+ elif v .ndim == 1 :
1800
+ yield k , IndexVariable ((k ,), v )
1801
+ else :
1802
+ raise AssertionError () # Already tested by _validate_indexers
1803
+ else :
1804
+ raise TypeError (type (v ))
1794
1805
1795
1806
def _get_indexers_coords_and_indexes (self , indexers ):
1796
1807
"""Extract coordinates and indexes from indexers.
@@ -1875,10 +1886,10 @@ def isel(
1875
1886
Dataset.sel
1876
1887
DataArray.isel
1877
1888
"""
1878
-
1879
1889
indexers = either_dict_or_kwargs (indexers , indexers_kwargs , "isel" )
1880
-
1881
- indexers_list = self ._validate_indexers (indexers )
1890
+ # Note: we need to preserve the original indexers variable in order to merge the
1891
+ # coords below
1892
+ indexers_list = list (self ._validate_indexers (indexers ))
1882
1893
1883
1894
variables = {} # type: Dict[Hashable, Variable]
1884
1895
indexes = {} # type: Dict[Hashable, pd.Index]
@@ -1894,19 +1905,21 @@ def isel(
1894
1905
)
1895
1906
if new_index is not None :
1896
1907
indexes [name ] = new_index
1897
- else :
1908
+ elif var_indexers :
1898
1909
new_var = var .isel (indexers = var_indexers )
1910
+ else :
1911
+ new_var = var .copy (deep = False )
1899
1912
1900
1913
variables [name ] = new_var
1901
1914
1902
- coord_names = set ( variables ). intersection ( self ._coord_names )
1915
+ coord_names = self ._coord_names & variables . keys ( )
1903
1916
selected = self ._replace_with_new_dims (variables , coord_names , indexes )
1904
1917
1905
1918
# Extract coordinates from indexers
1906
1919
coord_vars , new_indexes = selected ._get_indexers_coords_and_indexes (indexers )
1907
1920
variables .update (coord_vars )
1908
1921
indexes .update (new_indexes )
1909
- coord_names = set ( variables ). intersection ( self ._coord_names ). union ( coord_vars )
1922
+ coord_names = self ._coord_names & variables . keys () | coord_vars . keys ( )
1910
1923
return self ._replace_with_new_dims (variables , coord_names , indexes = indexes )
1911
1924
1912
1925
def sel (
@@ -2468,11 +2481,9 @@ def interp(
2468
2481
2469
2482
if kwargs is None :
2470
2483
kwargs = {}
2484
+
2471
2485
coords = either_dict_or_kwargs (coords , coords_kwargs , "interp" )
2472
- indexers = {
2473
- k : v .to_index_variable () if isinstance (v , Variable ) and v .ndim == 1 else v
2474
- for k , v in self ._validate_indexers (coords )
2475
- }
2486
+ indexers = dict (self ._validate_interp_indexers (coords ))
2476
2487
2477
2488
obj = self if assume_sorted else self .sortby ([k for k in coords ])
2478
2489
@@ -2497,26 +2508,25 @@ def _validate_interp_indexer(x, new_x):
2497
2508
"strings or datetimes. "
2498
2509
"Instead got\n {}" .format (new_x )
2499
2510
)
2500
- else :
2501
- return (x , new_x )
2511
+ return x , new_x
2502
2512
2503
2513
variables = {} # type: Dict[Hashable, Variable]
2504
2514
for name , var in obj ._variables .items ():
2505
- if name not in indexers :
2506
- if var . dtype . kind in "uifc" :
2507
- var_indexers = {
2508
- k : _validate_interp_indexer ( maybe_variable ( obj , k ), v )
2509
- for k , v in indexers . items ()
2510
- if k in var . dims
2511
- }
2512
- variables [ name ] = missing . interp (
2513
- var , var_indexers , method , ** kwargs
2514
- )
2515
- elif all (d not in indexers for d in var .dims ):
2516
- # keep unrelated object array
2517
- variables [name ] = var
2515
+ if name in indexers :
2516
+ continue
2517
+
2518
+ if var . dtype . kind in "uifc" :
2519
+ var_indexers = {
2520
+ k : _validate_interp_indexer ( maybe_variable ( obj , k ), v )
2521
+ for k , v in indexers . items ()
2522
+ if k in var . dims
2523
+ }
2524
+ variables [ name ] = missing . interp ( var , var_indexers , method , ** kwargs )
2525
+ elif all (d not in indexers for d in var .dims ):
2526
+ # keep unrelated object array
2527
+ variables [name ] = var
2518
2528
2519
- coord_names = set ( variables ). intersection ( obj ._coord_names )
2529
+ coord_names = obj ._coord_names & variables . keys ( )
2520
2530
indexes = {k : v for k , v in obj .indexes .items () if k not in indexers }
2521
2531
selected = self ._replace_with_new_dims (
2522
2532
variables .copy (), coord_names , indexes = indexes
@@ -2534,7 +2544,7 @@ def _validate_interp_indexer(x, new_x):
2534
2544
variables .update (coord_vars )
2535
2545
indexes .update (new_indexes )
2536
2546
2537
- coord_names = set ( variables ). intersection ( obj ._coord_names ). union ( coord_vars )
2547
+ coord_names = obj ._coord_names & variables . keys () | coord_vars . keys ( )
2538
2548
return self ._replace_with_new_dims (variables , coord_names , indexes = indexes )
2539
2549
2540
2550
def interp_like (
0 commit comments