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

fix multidim-value assignment -WIP

parent 7d8e8ef6
No related branches found
No related tags found
No related merge requests found
......@@ -320,37 +320,69 @@ class DictOfSeries:
elif _is_hashable(key):
if isinstance(value, pd.Series) or key not in self.columns:
self._insert(key, value)
elif _is_dios_like(value) or _is_nested_list_like(value):
raise ValueError("Incompatible indexer with multi-dimensional value")
else:
self._data.at[key][:] = value
else:
data = self.__getitem__(key)
assert isinstance(data, self.__class__), f"getitem returned data of type {type(data)}"
# special cases
if _is_dios_like(value):
self._setitem_dios(data, value)
elif _is_list_like(value):
self._setitem_listlike(data, value)
# default case
else:
for k in data.columns:
s = data._data.at[k]
s[:] = value
self._data.at[k][s.index] = s
def _setitem_listlike(self, data, value):
if not _is_nested_list_like(value):
raise ValueError(f"1D array-like value could not be broadcast to "
f"indexing result of shape (.., {len(data.columns)})")
if len(value) != len(data.columns):
raise ValueError(f"array-like value of shape (.., {len(value)}) could "
f"not be broadcast to indexing result of shape "
f"(.., {len(data.columns)})")
for i, k in enumerate(data.columns):
s = data._data.at[k]
s[:] = value[i]
self._data.at[k][s.index] = s
def _setitem_dios(self, data, value):
if len(data) != len(self.columns):
raise ValueError(f"length of axis 1 of input array does not match length of selected "
f"columns, input length {len(data)}, self length {len(self.columns)}")
""" Write values from a dios-like to self.
No justification or alignment on columns, but on indices.
If value has missing indices, nan's are inserted at that
locations, just like `series.loc[:]=val` or `df[:]=val` do.
Parameter
----------
data : dios
A maybe trimmed version of self
value : dios, pd.Dataframe
The value to set with the same column dimension like data
"""
if len(data) != len(value.columns):
raise ValueError(f"shape mismatch: values array of shape "
f"(.., {len(value.columns)}) could not "
f"be broadcast to indexing result of "
f"shape (.., {len(data.columns)})")
for i, k in enumerate(data):
l, r = data._data.at[k], value[value.columns[i]]
toset = l.index.intersection(r.index)
if not toset.empty:
self._data.at[k][toset] = r[toset]
# no drop - set Nans
# todrop = l.index.difference(r.index)
# if not todrop.empty:
# optimisation: drop performance depends on
# index length, even if todrop is empty
# self._data.at[k].drop(todrop, inplace=True)
dat = data._data.at[k]
val = value[value.columns[i]]
dat.loc[:] = val
self._data.at[k].loc[dat.index] = dat
@property
def loc(self):
......@@ -466,7 +498,7 @@ class DictOfSeries:
return self.to_string(method=repr, show_dimensions=showdim)
def to_string(self, max_rows=None, min_rows=None, max_cols=None,
na_rep=np.nan, show_dimensions=False,
na_rep='NaN', show_dimensions=False,
method=Opts.repr_indexed,
no_value=' ', empty_series_rep='no data',
col_delim=' | ', header_delim='=', col_space=None, ):
......
......@@ -94,13 +94,20 @@ class _LocIndexer(_Indexer):
rowkey, colkey = self._unpack_key(key)
if _is_dios_like(rowkey) or _is_dios_like(colkey):
raise ValueError("Cannot index with multidimensional key")
raise ValueError("Cannot index with multi-dimensional key")
# .loc[any, scalar]
if _is_hashable(colkey):
# .loc[dont-care, new-scalar] = val
if colkey not in self.obj.columns:
self.obj._insert(colkey, value)
# .loc[any, new-scalar] = multi-dim
elif _is_dios_like(value) or _is_nested_list_like(value):
raise ValueError("Incompatible indexer with multi-dimensional value")
# .loc[any, new-scalar] = val
else:
self._data.at[colkey].loc[rowkey] = value
......@@ -108,14 +115,24 @@ class _LocIndexer(_Indexer):
else:
i = None
data = self._data.loc[colkey]
try:
for i, s in enumerate(data):
s.loc[rowkey] = value
# special cases
if _is_list_like(value):
# todo, iter, check len, set .loc
raise NotImplementedError
elif _is_dios_like(value):
# todo, iter, align, set .loc
raise NotImplementedError
except Exception as e:
c = data.index[i] if i is not None else '?'
raise type(e)(f"failed for column {c}: " + str(e) ) from e
else:
try:
for i, s in enumerate(data):
s.loc[rowkey] = value
except Exception as e:
c = data.index[i] if i is not None else '?'
raise type(e)(f"failed for column {c}: " + str(e) ) from e
# #############################################################################
......@@ -161,7 +178,6 @@ class _iLocIndexer(_Indexer):
return new
def __setitem__(self, key, value):
# todo: value is dios-like see loc
rowkey, colkey = self._unpack_key(key)
if _is_dios_like(rowkey) or _is_dios_like(colkey):
raise ValueError("Cannot index with multidimensional key")
......@@ -174,14 +190,24 @@ class _iLocIndexer(_Indexer):
else:
i = None
data = self._data.iloc[colkey]
try:
for i, s in enumerate(data):
s.iloc[rowkey] = value
# special cases
if _is_list_like(value):
# todo, iter, check len, set .iloc
raise NotImplementedError
elif _is_dios_like(value):
# todo, iter, align, set .iloc
raise NotImplementedError
except Exception as e:
c = data.index[i] if i is not None else '?'
raise type(e)(f"failed for column {c}: " f"" + str(e)) from e
else:
try:
for i, s in enumerate(data):
s.iloc[rowkey] = value
except Exception as e:
c = data.index[i] if i is not None else '?'
raise type(e)(f"failed for column {c}: " f"" + str(e)) from e
# #############################################################################
......@@ -273,6 +299,14 @@ class _aLocIndexer(_Indexer):
idx = l.loc[rowkeys[i]].index.intersection(rindex)
l[idx] = r[idx]
elif _is_nested_list_like(value):
# todo: iterate + enumerate, check length, set
raise NotImplementedError
elif _is_list_like(value):
# todo: iterate columns, check length, set
raise NotImplementedError
# if no align is possible, fallback to .loc
else:
for i, c in enumerate(colkeys):
......
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