diff --git a/dios/dios.py b/dios/dios.py index f4533d8b058d1bb6d9d6123cf010ce0a24697a13..0f8304b8a65b82de1d094b09ca79aabd97ca67b7 100644 --- a/dios/dios.py +++ b/dios/dios.py @@ -320,15 +320,11 @@ class DictOfSeries: assert isinstance(data, self.__class__), f"getitem returned data of type {type(data)}" # special cases - # (I) Dios (ok) - # (II) list-like (fail) - # (III) nested lists-like (ok) - # NOTE: pd.Series considered list-like and also fail - # if they dont hold list-likes obj if _is_dios_like(value): self._setitem_dios(data, value) + # NOTE: pd.Series also considered list-like elif _is_list_like(value): - self._setitem_nested_listlike(data, value) + self._setitem_listlike(data, value) # default case else: @@ -337,15 +333,12 @@ class DictOfSeries: s[:] = value self._data.at[k][s.index] = s - def _setitem_nested_listlike(self, data, value): - # nested series, eg. `pd.Series([[1,2], [4,4]], dtype='O')` + def _setitem_listlike(self, data, value): + value = value.values if isinstance(value, pd.Series) else 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 " + raise ValueError(f"array-like value of length {len(value)} could " f"not be broadcast to indexing result of shape " f"(.., {len(data.columns)})") diff --git a/dios/indexer.py b/dios/indexer.py index d835de3a00bcc03d65df75463c5e27beed2d8e36..d54b49ea444c119a876710fab388cade79e9d9ea 100644 --- a/dios/indexer.py +++ b/dios/indexer.py @@ -6,6 +6,7 @@ from .dios import ( _is_bool_dios_like, _is_iterator) +import numpy as np import pandas as pd import pandas.core.common as ccom import pandas.core.dtypes.common as dcom @@ -50,16 +51,16 @@ class _Indexer: data = getattr(self._data, xloc)[colkey] def lenerr(vallen, datlen): - return ValueError(f"shape mismatch: values array of shape (.., {vallen}) could " + return ValueError(f"shape mismatch: value array of shape (.., {vallen}) could " f"not be broadcast to indexing result of shape (.., {datlen})") - def set_(data, value, iter=False): + def set_(data, value, iter=False, align=False): + assert not (iter and align), "only one can be True" c = "?" try: for i, c in enumerate(data.index): dat = data.at[c] dat_xloc = getattr(dat, xloc) - val = value[i] if iter else value # a hashable rowkey (.xloc[3, c] = value) : # loc: rowkey not present in self -> prevent that .loc create a new item @@ -78,21 +79,23 @@ class _Indexer: elif len(dat_xloc[rowkey]) == 0: continue + # unpack the value if necessary + if iter: + val = value[i] + elif align: + val = value[c] if c in value else np.nan + else: + val = value + dat_xloc[rowkey] = val except Exception as e: raise type(e)(f"failed for column {c}: " + str(e)) from e if _is_dios_like(value): - if len(value) == 1: - value = value.squeeze() - elif len(value) != len(data): - raise lenerr(len(value), len(data)) - else: - value = [value[c] for c in value.columns] - # fall trough to nested list + set_(data, value, align=True) - if _is_nested_list_like(value): + elif _is_list_like(value): if len(value) != len(data): raise lenerr(len(value), len(data)) set_(data, value, iter=True) @@ -314,7 +317,7 @@ class _aLocIndexer(_Indexer): dat.loc[rk] = value # no align, no merci - elif _is_nested_list_like(value): + elif _is_list_like(value): if len(colkeys) != len(value): raise ValueError(f"shape mismatch: values array of shape " f"(.., {len(value)}) could not "