Skip to content

Commit 69b7a12

Browse files
committed
BUG: fix initialization of Series with dict containing NaN as key
closes pandas-dev#18480
1 parent 38f41e6 commit 69b7a12

File tree

3 files changed

+48
-2
lines changed

3 files changed

+48
-2
lines changed

doc/source/whatsnew/v0.22.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -205,4 +205,5 @@ Other
205205

206206
- Improved error message when attempting to use a Python keyword as an identifier in a numexpr query (:issue:`18221`)
207207
- Fixed a bug where creating a Series from an array that contains both tz-naive and tz-aware values will result in a Series whose dtype is tz-aware instead of object (:issue:`16406`)
208+
- Fixed construction of ``Series`` from ``dict`` containing ``NaN`` as key (:issue:`18480`)
208209
-

pandas/core/indexes/base.py

+27-2
Original file line numberDiff line numberDiff line change
@@ -2847,8 +2847,33 @@ def get_indexer_for(self, target, **kwargs):
28472847

28482848
@Appender(_index_shared_docs['_get_values_from_dict'])
28492849
def _get_values_from_dict(self, data):
2850-
return lib.fast_multiget(data, self.values,
2851-
default=np.nan)
2850+
# MultiIndex doesn't support isna()
2851+
if not data or (not hasattr(self, 'levels') and
2852+
not isna(self.values).any()):
2853+
# lib.fast_multiget doesn't support arbitrary dict subclasses
2854+
if not data.__class__ is dict:
2855+
data = dict(data)
2856+
return lib.fast_multiget(data, self.values,
2857+
default=np.nan)
2858+
else:
2859+
# Looking for NaN in dict doesn't work ({np.nan : 1}[float('nan')]
2860+
# raises KeyError), so we iterate the entire dict, and align
2861+
keys, values = zip(*compat.iteritems(data))
2862+
keys = Index(keys)
2863+
values = np.array(values, dtype='object')
2864+
if not self.equals(keys):
2865+
locs = self.get_indexer(keys)
2866+
order = - np.ones(len(self), dtype=int)
2867+
order[locs] = np.arange(len(keys))
2868+
values = values[order]
2869+
2870+
nan_idxs = np.where(order == -1)[0]
2871+
if len(nan_idxs):
2872+
if is_integer_dtype(data):
2873+
values = values.astype(float)
2874+
values[nan_idxs] = np.nan
2875+
return lib.maybe_convert_objects(values)
2876+
28522877

28532878
def _maybe_promote(self, other):
28542879
# A hack, but it works

pandas/tests/series/test_constructors.py

+20
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,26 @@ def test_constructor_dict(self):
625625
expected.iloc[1] = 1
626626
assert_series_equal(result, expected)
627627

628+
def test_constructor_dict_nan_key(self):
629+
# GH 18480
630+
d = {1: 'a', 2: 'b', np.nan: 'c'}
631+
result = Series(d).sort_index()
632+
expected = Series(['a', 'b', 'c'], index=[1, 2, np.nan])
633+
assert_series_equal(result, expected)
634+
635+
# Different NaNs:
636+
d = {1: 'a', 2: 'b', float('nan'): 'c', float('nan'): 'd'}
637+
result = Series(d).sort_values()
638+
expected = Series(['a', 'b', 'c', 'd'], index=[1, 2, np.nan, np.nan])
639+
assert_series_equal(result, expected)
640+
641+
# MultiIndex:
642+
d = {(1, 1): 'a', (2, 2): 'b', (3, np.nan): 'c'}
643+
result = Series(d).sort_values()
644+
expected = Series(['a', 'b', 'c'],
645+
index=Index([(1, 1), (2, 2), (3, np.nan)]))
646+
assert_series_equal(result, expected)
647+
628648
def test_constructor_dict_datetime64_index(self):
629649
# GH 9456
630650

0 commit comments

Comments
 (0)