From 2214ffa808bc9ab2997f29708f4a69747a4289ea Mon Sep 17 00:00:00 2001
From: Bert Palm <bert.palm@ufz.de>
Date: Thu, 5 Mar 2020 21:32:44 +0100
Subject: [PATCH] fixed aloc, added bool-list support

---
 dios/locator.py | 39 ++++++++++++++++++++++++++++++++-------
 1 file changed, 32 insertions(+), 7 deletions(-)

diff --git a/dios/locator.py b/dios/locator.py
index 6dadb59..d36dd2e 100644
--- a/dios/locator.py
+++ b/dios/locator.py
@@ -213,7 +213,7 @@ class _aLocIndexer(_Indexer):
         super().__init__(*args, **kwargs)
 
     def __setitem__(self, key, value):
-        rowkeys, colkeys = self._unpack_key_aloc(key)
+        rowkeys, colkeys, _ = self._unpack_key_aloc(key)
 
         # full align (rows+cols) - align given dios with ourself
         if _is_dios_like(value):
@@ -226,8 +226,11 @@ class _aLocIndexer(_Indexer):
 
         # row align - align given series to every series in ourself
         elif isinstance(value, pd.Series):
+            r, rindex = value, value.index
             for i, c in enumerate(colkeys):
-                self._data.at[c].loc[rowkeys[i]] = value
+                l = self._data.at[c]
+                idx = l.loc[rowkeys[i]].index.intersection(rindex)
+                l[idx] = r[idx]
 
         # if no align is possible, fallback to .loc
         else:
@@ -235,10 +238,13 @@ class _aLocIndexer(_Indexer):
                 self._data.at[c].loc[rowkeys[i]] = value
 
     def __getitem__(self, key):
-        rowkeys, colkeys = self._unpack_key_aloc(key)
-        new = self._dios.copy_empty(columns=False)
-        for i, c in enumerate(colkeys):
-            new._data.at[c] = self._dios.loc[rowkeys[i], c]
+        rowkeys, colkeys, lowdim = self._unpack_key_aloc(key)
+        if lowdim:
+            new = self._data.at[colkeys[0]].loc[rowkeys[0]]
+        else:
+            new = self._dios.copy_empty(columns=False)
+            for i, c in enumerate(colkeys):
+                new._data.at[c] = self._dios.loc[rowkeys[i], c]
         return new
 
     def _unpack_key_aloc(self, key):
@@ -246,6 +252,7 @@ class _aLocIndexer(_Indexer):
         Return a list of row indexer and a list of existing(!) column labels.
         Both list always have the same length and also could be empty together.
         """
+        lowdim = False
         # boolean dios
         if _is_dios_like(key):
             colkey = self._dios.columns.intersection(key.columns).to_list()
@@ -265,11 +272,20 @@ class _aLocIndexer(_Indexer):
             # make column-slice from scalar
             if _is_hashable(colkey):
                 colkey = [colkey] if colkey in self._dios.columns else []
+                lowdim = True
 
             # pd.Series(a=True, b=False, x=True), columns:[a,b,c,d,] -> [a,]
             elif _is_bool_series(colkey):
                 colkey = self._dios.columns.intersection(colkey[colkey].index).to_list()
 
+            # special case boolean list-like:
+            # no align, no gratefulness, no mercy
+            elif _is_bool_indexer(colkey):
+                if len(colkey) != len(self._dios):
+                    raise ValueError(f"length mismatch for non-alignable boolean list. "
+                                     f"column length: {len(self._dios)}, given length: {len(colkey)}")
+                colkey = self._dios.columns[colkey].to_list()
+
             # filter only existing columns from list
             elif _is_list_like_not_nested(colkey):
                 colkey = [c for c in self._dios.columns if c in colkey]
@@ -292,6 +308,15 @@ class _aLocIndexer(_Indexer):
                     rkeys += [self._data.at[c].index.intersection(rowkey.index)]
                 rowkey = rkeys
 
+            # special case boolean list-like:
+            # no align, no gratefulness, no mercy
+            elif _is_bool_indexer(rowkey):
+                blength = len(rowkey)
+                fail = [c for c in colkey if len(self._data.at[c]) != blength]
+                if fail:
+                    raise ValueError(f"Length mismatch for bool array for column(s): {fail}")
+                rowkey = [rowkey] * len(colkey)
+
             # filter only existing rows from list
             elif _is_list_like_not_nested(rowkey):
                 rkeys = []
@@ -302,7 +327,7 @@ class _aLocIndexer(_Indexer):
             else:
                 rowkey = [rowkey] * len(colkey)
 
-        return rowkey, colkey
+        return rowkey, colkey, lowdim
 
 # #############################################################################
 
-- 
GitLab