Wrap a pandas.MultiIndex as an xarray compatible index.
| 1023 | |
| 1024 | |
| 1025 | class PandasMultiIndex(PandasIndex): |
| 1026 | """Wrap a pandas.MultiIndex as an xarray compatible index.""" |
| 1027 | |
| 1028 | index: pd.MultiIndex |
| 1029 | dim: Hashable |
| 1030 | coord_dtype: Any |
| 1031 | level_coords_dtype: dict[Hashable | None, Any] |
| 1032 | |
| 1033 | __slots__ = ("coord_dtype", "dim", "index", "level_coords_dtype") |
| 1034 | |
| 1035 | def __init__(self, array: Any, dim: Hashable, level_coords_dtype: Any = None): |
| 1036 | super().__init__(array, dim) |
| 1037 | |
| 1038 | # default index level names |
| 1039 | names = [] |
| 1040 | for i, idx in enumerate(self.index.levels): |
| 1041 | name = idx.name or f"{dim}_level_{i}" |
| 1042 | if name == dim: |
| 1043 | raise ValueError( |
| 1044 | f"conflicting multi-index level name {name!r} with dimension {dim!r}" |
| 1045 | ) |
| 1046 | names.append(name) |
| 1047 | self.index.names = names |
| 1048 | |
| 1049 | if level_coords_dtype is None: |
| 1050 | level_coords_dtype = { |
| 1051 | idx.name: get_valid_numpy_dtype(idx) for idx in self.index.levels |
| 1052 | } |
| 1053 | self.level_coords_dtype = level_coords_dtype |
| 1054 | |
| 1055 | def _replace(self, index, dim=None, level_coords_dtype=None) -> PandasMultiIndex: |
| 1056 | if dim is None: |
| 1057 | dim = self.dim |
| 1058 | index.name = dim |
| 1059 | if level_coords_dtype is None: |
| 1060 | level_coords_dtype = self.level_coords_dtype |
| 1061 | return type(self)(index, dim, level_coords_dtype) |
| 1062 | |
| 1063 | @classmethod |
| 1064 | def from_variables( |
| 1065 | cls, |
| 1066 | variables: Mapping[Any, Variable], |
| 1067 | *, |
| 1068 | options: Mapping[str, Any], |
| 1069 | ) -> PandasMultiIndex: |
| 1070 | _check_dim_compat(variables) |
| 1071 | dim = next(iter(variables.values())).dims[0] |
| 1072 | |
| 1073 | index = pd.MultiIndex.from_arrays( |
| 1074 | [var.values for var in variables.values()], names=list(variables.keys()) |
| 1075 | ) |
| 1076 | index.name = dim |
| 1077 | level_coords_dtype = {name: var.dtype for name, var in variables.items()} |
| 1078 | obj = cls(index, dim, level_coords_dtype=level_coords_dtype) |
| 1079 | |
| 1080 | return obj |
| 1081 | |
| 1082 | @classmethod |
no outgoing calls
searching dependent graphs…