What does dict(mapping) actually do?
Background:
Python's docs suggest there are three possible paths when constructing a dict, one of which is with a Mapping.
A pandas series is similar to a dict in some ways, and coercing to a dict works as expected:
In [27]: series=pd.Series({'a':2,'b':3})
In [28]: dict(series)
Out[28]: {'a': 2, 'b': 3}
But when inside a ChainMap, this goes awry:
In [25]: dict(ChainMap(series))
... which should be equivalent to the first expression, I think, but instead...
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/pandas/core/index.py in get_value(self, series, key)
1789 try:
-> 1790 return self._engine.get_value(s, k)
1791 except KeyError as e1:
pandas/index.pyx in pandas.index.IndexEngine.get_value (pandas/index.c:3204)()
pandas/index.pyx in pandas.index.IndexEngine.get_value (pandas/index.c:2903)()
pandas/index.pyx in pandas.index.IndexEngine.get_loc (pandas/index.c:3843)()
pandas/hashtable.pyx in pandas.hashtable.PyObjectHashTable.get_item (pandas/hashtable.c:12265)()
pandas/hashtable.pyx in pandas.hashtable.PyObjectHashTable.get_item (pandas/hashtable.c:12216)()
KeyError: 2
During handling of the above exception, another exception occurred:
IndexError Traceback (most recent call last)
<ipython-input-25-ffe959c53a67> in <module>()
----> 1 dict(ChainMap(series))
/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/collections/__init__.py in __getitem__(self, key)
865 for mapping in self.maps:
866 try:
--> 867 return mapping[key] # can't use 'key in mapping' with defaultdict
868 except KeyError:
869 pass
/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/pandas/core/series.py in __getitem__(self, key)
555 def __getitem__(self, key):
556 try:
--> 557 result = self.index.get_value(self, key)
558
559 if not np.isscalar(result):
/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/pandas/core/index.py in get_value(self, series, key)
1794
1795 try:
-> 1796 return tslib.get_value_box(s, key)
1797 except IndexError:
1798 raise
pandas/tslib.pyx in pandas.tslib.get_value_box (pandas/tslib.c:16375)()
pandas/tslib.pyx in pandas.tslib.get_value_box (pandas/tslib.c:16126)()
IndexError: index out of bounds
FWIW this does work:
In [29]: dict(ChainMap(dict(series)))
Out[29]: {'a': 2, 'b': 3}
...so ChainMap seems to be calling parts of the interface of Series that dict doesn't call. I can't work out what, because I can't seem to find Python-code that replicates what dict(mapping) does.
It looks like series aren't really true mappings... Note that iterating over the series yields the values, not the keys:
>>> list(series)
[2, 3]
collections.ChainMap relies on the fact that iterating over a mapping should yield the keys.
Apparently, the dict constructor doesn't rely on this fact (IIRC, it uses the .keys method -- for which pandas returns a suitable object).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With