Skip to content
Snippets Groups Projects
Commit f810894d authored by Bert Palm's avatar Bert Palm 🎇
Browse files

getitem fine

parent ba8c0b03
No related branches found
No related tags found
2 merge requests!2Develop,!1complete rework
......@@ -5,6 +5,7 @@ from dios.errors import *
import pandas as pd
import numpy as np
import operator as op
from functools import partialmethod
from functools import wraps
from collections import OrderedDict
......@@ -186,45 +187,27 @@ class DictOfSeries:
- ``dios['a']`` -> return a pd.Series
- ``dios[iterable]`` -> return a DictOfSeries of all given columns [1]
- ``dios[slice]`` -> return a sliced DictOfSeries of all(!) columns in the dios
Notes:
- [1] If ``iterable`` contains any(!) label that does not exist, a KeyError is raised.
"""
# prepare
if is_iterator(key):
key = list(key)
# special case single label
if isinstance(key, str):
self._check_keys([key])
return self._get_item(key)
if isinstance(key, slice):
return self._slice(self.columns, key)
if is_list_like(key) and not is_nested_list_like(key):
self._check_keys(key)
return self._getitem_listlike(key)
raise KeyError(f"{key}")
if key in self.columns:
new = self._get_item(key)
else:
raise KeyError(key)
else:
keys, ixs = self._get_keys_and_indexer(key)
new = self.copy_empty()
for i, _ in enumerate(keys):
key, ix = keys[i], ixs[i]
new._data[key] = self._get_item(key)[ix]
return new
def _get_item(self, key):
# return always a pd.Series
return self._data[key]
def _getitem_listlike(self, keys):
new = self.copy_empty()
for k in keys:
new._data[k] = self._get_item(k)
return new
def _slice(self, keys, slicer):
""" Return a slice of self"""
new = self.copy_empty()
for k in keys:
new._data[k] = self._get_item(k)[slicer]
return new
def __setitem__(self, key, value):
"""
Set items:
......@@ -253,6 +236,52 @@ class DictOfSeries:
for tup in gen:
self._set_item(*tup)
def _setitem(self, keys, ixs, val):
"""Return a generator that yield (key, indexer, value) for all keys"""
if is_iterator(val):
val = list(val)
diosl, dfl, nlistl = is_dios_like(val), is_dataframe_like(val), is_nested_list_like(val)
if diosl or dfl or nlistl and len(val) != len(keys):
raise ValueError(f"could not broadcast input array with length {len(val)}"
f" into dios of length {len(keys)}")
# now we have everything we need: key, indexer, value
# so we just pack it nice and cosy and let setitem
# do the dirty work.
for i, _ in enumerate(keys):
key, ix = keys[i], ixs[i]
if dfl or diosl:
yield key, ix, val[val.columns[i]]
elif nlistl:
yield key, ix, val[i]
else:
yield key, ix, val
def _set_item(self, key, ix, val):
"Set a value (scalar or list or series)"
ser = self._data[key]
if is_series_like(val):
left = ser[ix]
index = left.index.intersection(val.index)
if not index.empty:
left.loc[index] = val.loc[index].copy()
else:
ser[ix] = val
def _insert(self, key, val):
""""""
if isinstance(val, DictOfSeries):
val = val.squeeze()
elif is_list_like(val) and not is_nested_list_like(val):
val = pd.Series(val)
if not isinstance(val, pd.Series):
raise ValueError(f"Only pd.Series can be inserted directly")
val = cast_to_itype(val, self._itype, policy=self._policy)
self._data[key] = val.copy(deep=True)
def _get_keys_and_indexer(self, key):
""" Determine keys and indexer
Notes:
......@@ -330,52 +359,6 @@ class DictOfSeries:
# now we have a valid indexer (a slice or a bool array) for every series
return keys, indexers
def _setitem(self, keys, ixs, val):
"""Return a generator that yield (key, indexer, value) for all keys"""
if is_iterator(val):
val = list(val)
diosl, dfl, nlistl = is_dios_like(val), is_dataframe_like(val), is_nested_list_like(val)
if diosl or dfl or nlistl and len(val) != len(keys):
raise ValueError(f"could not broadcast input array with length {len(val)}"
f" into dios of length {len(keys)}")
# now we have everything we need: key, indexer, value
# so we just pack it nice and cosy and let setitem
# do the dirty work.
for i, _ in enumerate(keys):
key, ix = keys[i], ixs[i]
if dfl or diosl:
yield key, ix, val[val.columns[i]]
elif nlistl:
yield key, ix, val[i]
else:
yield key, ix, val
def _insert(self, key, val):
""""""
if isinstance(val, DictOfSeries):
val = val.squeeze()
elif is_list_like(val) and not is_nested_list_like(val):
val = pd.Series(val)
if not isinstance(val, pd.Series):
raise ValueError(f"Only pd.Series can be inserted directly")
val = cast_to_itype(val, self._itype, policy=self._policy)
self._data[key] = val.copy(deep=True)
def _set_item(self, key, ix, val):
"Set a value (scalar or list or series)"
ser = self._data[key]
if is_series_like(val):
left = ser[ix]
index = left.index.intersection(val.index)
if not index.empty:
left.loc[index] = val.loc[index].copy()
else:
ser[ix] = val
@property
def loc(self):
return _LocIndexer(self)
......@@ -411,7 +394,7 @@ class DictOfSeries:
@property
def empty(self):
return all(self._data[c].empty for c in self._data)
return len(self) == 0 or all(self._data[c].empty for c in self._data)
def all(self):
return pd.Series([self._data[c].any() for c in self._data])
......@@ -462,19 +445,20 @@ class DictOfSeries:
new._itype = self.itype
return new
def _op1_wrap(op):
def anyop(self):
with reraise(f"'{OP_MAP[op]}dios' failed: "):
new = self.copy_empty()
for k in self:
new[k] = op(self._data[k])
return new
def anyop(self, op, ):
new = self.copy_empty()
with reraise(f"'{OP_MAP[op]} dios' failed: "):
for k in self:
new[k] = op(self._data[k])
return new
return anyop
def foo(self, x):
raise ValueError('dnsjkncsncj')
__neg__ = _op1_wrap(op.neg)
__abs__ = _op1_wrap(op.abs)
__invert__ = _op1_wrap(op.inv)
__neg__ = partialmethod(anyop, op.neg)
__abs__ = partialmethod(anyop, op.abs)
# __invert__ = partialmethod(anyop, op.inv)
__invert__ = partialmethod(anyop, foo)
def _op2(self, other, op, inplace=False):
new = self.copy_empty()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment