def _parsevals(value, arrayonly=False): if isinstance(value, NamedIndex): val = value._names elif iterable(value): val = np.asarray(ll(value), dtype=object) if checkany(val, lambda x: not isstring(x)): raise TypeError('index names must be string') else: if arrayonly: raise TypeError('index names must be an array') if not isstring(value): raise TypeError('index name must be a string') val = value return val
def idsof(self, names: Union[str, Iterable[str]], safe: bool = False) -> Union[None, int, List[Union[None, int]]]: if isstring(names): ids = self._nidct.get(names, None) if not safe and missing(ids): raise KeyError(f'unknown index name {names}') else: ids = [ self._nidct.get(n, None) if isstring(n) else n for n in names ] if not safe and checkany(ids, missing): raise KeyError('unknown index name(s)') return ids
def delete(self, pos: Indices2D, axis: Optional[int] = 0, inline: bool = False) -> StructuredArray: narr = self if inline else self.copy() if isstring(pos): del narr._arrs[pos] return narr sids, aids = self._parseids(pos, axis=axis, mapslice=False) slic = isinstance(sids, slice) and sids == slice(None) alic = isinstance(aids, slice) and aids == slice(None) and (missing(axis) or axis == 0) if slic and alic: narr._arrs = OrderedDict() narr._length = None elif slic and not alic: if listable(aids) and len(aids) == 1 and aids[0] < 0: aids = aids[ 0] # fix the issue that currently negative indices are ignored by np.delete for k, v in narr._arrs.items(): narr._arrs[k] = np.delete(v, aids) narr._length = len(narr._arrs[l(narr._arrs.keys())[0]]) elif not slic and alic: if isinstance(sids, slice) or sids.dtype.kind not in ('S', 'U'): sids = narr.names[sids] for k in sids: del narr._arrs[k] else: raise IndexError('unable to delete portion of the array') return narr
def put(self, pos: Indices2D, value: Any, axis: Optional[int] = 0, inline: bool = False) -> StructuredArray: narr = self if inline else self.copy() vals = self._parsevals(value) if isstring(pos): if not isinstance(vals, np.ndarray): raise ValueError('input array not in 1-dimensional') if missing(narr._length): narr._length = vals.shape[0] elif narr._length != vals.shape[0]: raise ValueError('input array size not match') narr._arrs[pos] = vals.copy() else: sids, aids = self._parseids(pos, axis=axis) if not isinstance(vals, list): for k in sids: narr._arrs[k][aids] = vals else: if len(sids) != len(vals): raise ValueError('input names and values size not match') for k, vals in zip(sids, vals): narr._arrs[k][aids] = vals return narr
def _parseids(self, ids): if isinstance(ids, tuple): raise IndexError('too many dimensions for array') if (listable(ids) and checkany(ids, isstring)) or isstring(ids): return self.idsof(ids, safe=False) if listable(ids) and checkany(ids, lambda v: isinstance(v, bool)): return np.where(ids)[0] if ids is None: return slice(None) return ids
def put(self, pos: Indices, value: Union[str, Iterable[str]], inline: bool = False) -> NamedIndex: pos = self._parseids(pos) val = self._parsevals(value) nid = self if inline else self.copy() if isinstance(pos, int): if not isstring(val): raise TypeError('cannot assign multiple names to one position') nid._nidct.pop(nid._names[pos]) if val in nid._nidct: raise KeyError('index names not unique') nid._names[pos], nid._nidct[val] = val, pos else: nid._names[pos] = val nid._reindex() return nid
def _parseids(self, idx, axis=None, mapslice=True): if missing(axis): sids, aids = (idx, slice(None)) if not isinstance(idx, tuple) else \ (idx[0], slice(None)) if len(idx) == 1 else idx else: if isinstance(idx, tuple): raise IndexError('too many dimensions for array') if axis not in (0, 1): raise IndexError('invalid axis value') sids, aids = (idx, slice(None)) if axis == 0 else (slice(None), idx) def _wrap(ids): if ids is None: return slice(None) if isinstance(ids, slice): return ids if not listable(ids): return [ids] return ids sids, aids = smap((sids, aids), _wrap) if (isinstance(sids, slice) and mapslice) or ( listable(sids) and checkany(sids, lambda x: not isstring(x))): sids = self.names[sids] return sids, aids
def take(self, pos: Indices2D, axis: Optional[int] = 0) -> StructuredArray: if isstring(pos): return self._arrs[pos] sids, aids = self._parseids(pos, axis=axis) return StructuredArray([(k, self._arrs[k][aids]) for k in sids])