def __delitem__(self, key): if is_float(key): msg = 'array index cannot be float; please cast to int' raise KeyError(msg) elif is_bool(key): msg = 'logical indexing must provide an iterable of full length' raise KeyError(msg) elif is_string(key): msg = 'array index cannot be string' raise TypeError(msg) elif isinstance(key, tuple): msg = ('tuple is ambiguous because it can refer to dual-indexing; ' 'convert index to list') raise TypeError(msg) elif is_integer(key): # We can only drop by pd.Series index (not using row numbers). # So, we ensure that the Series index is the same as row numbers. self._data.reset_index(drop=True, inplace=True) del self._data[key] self.dtype = infer_dtype(self._data) elif isinstance(key, slice): key = range(*key.indices(len(self))) self._del_by_iterable(key) elif isinstance(key, Iterable): if infer_dtype(key) is bool: key = self._convert_logical_index_to_int_index(key) self._del_by_iterable(key) self.dtype = infer_dtype(self._data) else: msg = 'index can only be int or iterable (int, bool)' raise IndexError(msg)
def __setitem__(self, key, value): if is_float(key): msg = 'array index cannot be float; please cast to int' raise KeyError(msg) elif is_bool(key): msg = 'logical indexing must provide an iterable of full length' raise KeyError(msg) elif is_string(key): msg = 'array index cannot be string' raise TypeError(msg) elif isinstance(key, tuple): msg = ('tuple is ambiguous because it can refer to dual-indexing; ' 'convert index to list') raise TypeError(msg) elif is_integer(key): if self._is_valid_dtype_element(value): self._data.iloc[key] = value else: msg = 'value type does not match array dtype = {}' raise ValueError(msg.format(self.dtype.__name__)) else: if is_scalar(value): if self._is_valid_dtype_element(value): self._data.iloc[key] = value else: msg = 'value type does not match array dtype = {}' raise ValueError(msg.format(self.dtype.__name__)) else: if self._is_valid_dtype_iterable(value): self._data.iloc[key] = value else: msg = 'value type does not match array dtype = {}' raise ValueError(msg.format(self.dtype.__name__)) self._data = self._data.astype(object) self.dtype = infer_dtype(self._data)
def extend(self, other): assert isinstance(other, type(self)) if (self.dtype == other.dtype) or (self.dtype is type(None)): self._data = self._data.append(other._data, ignore_index=True) self.dtype = infer_dtype(self._data) else: msg = 'cannot extend with a non-{} object'.format(type(self)) raise TypeError(msg)
def __init__(self, data=[]): if isinstance(data, type(self)): # Data is not copied a la pd.Series self._data = data._data self.dtype = data.dtype elif isinstance(data, _ArraySlice): self._data = data._data self.dtype = infer_dtype(self._data) else: self._data = pd.Series(data, dtype=object) # This step is really slow! Avoid this when possible. for index, value in enumerate(self._data): try: if np.isnan(value): self._data[index] = None except (TypeError, ValueError): pass self.dtype = infer_dtype(self._data)
def _convert_logical_index_to_int_index(self, key): assert infer_dtype(key) is bool if get_length(key) == len(self): if any([e is None for e in key]): msg = 'logical index contains missing values (None)' raise IndexError(msg) else: key = [i for i, k in enumerate(key) if k] else: msg = 'logical index does not match array length' raise IndexError(msg) return key
def __getitem__(self, key): if is_float(key): msg = 'array index cannot be float; please cast to int' raise TypeError(msg) elif is_bool(key): msg = 'logical indexing must provide an iterable of full length' raise TypeError(msg) elif is_string(key): msg = 'array index cannot be string' raise TypeError(msg) elif isinstance(key, tuple): msg = ('tuple is ambiguous because it can refer to dual-indexing; ' 'convert index to list') raise TypeError(msg) elif is_integer(key): return self._data.iloc[key] elif isinstance(key, Iterable) and infer_dtype(key) is bool: key = self._convert_logical_index_to_int_index(key) return type(self)(_ArraySlice(self._data.iloc[key])) else: return type(self)(_ArraySlice(self._data.iloc[key]))
def _parse_colkey(self, colkey): # FIXME: self._data can handle slices. Should I not convert slice to # list of ints here? if isinstance(colkey, slice): colkey = range(*colkey.indices(len(self))) if is_iterable_string(colkey): colkey = [self._names_to_index[k] for k in colkey] if infer_dtype(colkey) is bool: if any([k is None for k in colkey]): msg = 'logical index contains missing values (None(s))' raise IndexError(msg) else: if get_length(colkey) == len(self): colkey = [i for i, k in enumerate(colkey) if k] else: msg = 'logical index does not match number of columns' raise IndexError(msg) valid = range(self._ncol) if not all([k in valid for k in colkey]): msg = 'invalid column key' raise KeyError(msg) return colkey