def __getitem__(self, key): """Returns values based on `key`. All the functionality of ``ndarray.__getitem__()`` is supported (including fancy indexing), plus a special support for expressions: Parameters ---------- key : string The corresponding ctable column name will be returned. If not a column name, it will be interpret as a boolean expression (computed via `ctable.eval`) and the rows where these values are true will be returned as a NumPy structured array. See Also -------- ctable.eval """ # First, check for integer if isinstance(key, _inttypes): # Get a copy of the len-1 array ra = self._arr1.copy() # Fill it ra[0] = tuple([self.cols[name][key] for name in self.names]) return ra[0] # Slices elif type(key) == slice: (start, stop, step) = key.start, key.stop, key.step if step and step <= 0: raise NotImplementedError("step in slice can only be positive") # Multidimensional keys elif isinstance(key, tuple): if len(key) != 1: raise IndexError("multidimensional keys are not supported") return self[key[0]] # List of integers (case of fancy indexing), or list of column names elif type(key) is list: if len(key) == 0: return np.empty(0, self.dtype) strlist = all(isinstance(v, _strtypes) for v in key) # Range of column names if strlist: cols = [self.cols[name] for name in key] return ctable(cols, key) # Try to convert to a integer array try: key = np.array(key, dtype=np.int_) except: raise IndexError( "key cannot be converted to an array of indices") return np.fromiter((self[i] for i in key), dtype=self.dtype, count=len(key)) # A boolean array (case of fancy indexing) elif hasattr(key, "dtype"): if key.dtype.type == np.bool_: return self._where(key) elif np.issubsctype(key, np.int_): # An integer array return np.array([tuple(self[i]) for i in key], dtype=self.dtype) else: raise IndexError( "arrays used as indices must be integer (or boolean)") # Column name or expression elif isinstance(key, _strtypes): if key not in self.names: # key is not a column name, try to evaluate arr = self.eval(key, depth=4) if arr.dtype.type != np.bool_: raise IndexError("`key` %s does not represent a boolean " "expression" % key) return self._where(arr) return self.cols[key] # All the rest not implemented else: raise NotImplementedError("key not supported: %s" % repr(key)) # From now on, will only deal with [start:stop:step] slices # Get the corrected values for start, stop, step (start, stop, step) = slice(start, stop, step).indices(self.len) # Build a numpy container n = utils.get_len_of_range(start, stop, step) ra = np.empty(shape=(n, ), dtype=self.dtype) # Fill it for name in self.names: ra[name][:] = self.cols[name][start:stop:step] return ra
def __getitem__(self, key): """Returns values based on `key`. All the functionality of ``ndarray.__getitem__()`` is supported (including fancy indexing), plus a special support for expressions: Parameters ---------- key : string The corresponding ctable column name will be returned. If not a column name, it will be interpret as a boolean expression (computed via `ctable.eval`) and the rows where these values are true will be returned as a NumPy structured array. See Also -------- ctable.eval """ # First, check for integer if isinstance(key, _inttypes): # Get a copy of the len-1 array ra = self._arr1.copy() # Fill it ra[0] = tuple([self.cols[name][key] for name in self.names]) return ra[0] # Slices elif type(key) == slice: (start, stop, step) = key.start, key.stop, key.step if step and step <= 0: raise NotImplementedError("step in slice can only be positive") # Multidimensional keys elif isinstance(key, tuple): if len(key) != 1: raise IndexError("multidimensional keys are not supported") return self[key[0]] # List of integers (case of fancy indexing), or list of column names elif type(key) is list: if len(key) == 0: return np.empty(0, self.dtype) strlist = [type(v) for v in key] == [str for v in key] # Range of column names if strlist: cols = [self.cols[name] for name in key] return ctable(cols, key) # Try to convert to a integer array try: key = np.array(key, dtype=np.int_) except: raise IndexError( "key cannot be converted to an array of indices") return np.fromiter((self[i] for i in key), dtype=self.dtype, count=len(key)) # A boolean array (case of fancy indexing) elif hasattr(key, "dtype"): if key.dtype.type == np.bool_: return self._where(key) elif np.issubsctype(key, np.int_): # An integer array return np.array([self[i] for i in key], dtype=self.dtype) else: raise IndexError( "arrays used as indices must be integer (or boolean)") # Column name or expression elif isinstance(key, _strtypes): if key not in self.names: # key is not a column name, try to evaluate arr = self.eval(key, depth=4) if arr.dtype.type != np.bool_: raise IndexError( "`key` %s does not represent a boolean " "expression" % key) return self._where(arr) return self.cols[key] # All the rest not implemented else: raise NotImplementedError("key not supported: %s" % repr(key)) # From now on, will only deal with [start:stop:step] slices # Get the corrected values for start, stop, step (start, stop, step) = slice(start, stop, step).indices(self.len) # Build a numpy container n = utils.get_len_of_range(start, stop, step) ra = np.empty(shape=(n,), dtype=self.dtype) # Fill it for name in self.names: ra[name][:] = self.cols[name][start:stop:step] return ra