Skip to content

Commit dfb4cae

Browse files
committed
Makes changes based on feedback from @jreback
1 parent 527f879 commit dfb4cae

File tree

10 files changed

+102
-106
lines changed

10 files changed

+102
-106
lines changed

pandas/core/series.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@
4040
_try_sort,
4141
_maybe_match_name,
4242
SettingWithCopyError,
43-
_maybe_box_datetimelike,
44-
_dict_compat)
43+
_maybe_box_datetimelike)
4544
from pandas.core.index import (Index, MultiIndex, InvalidIndexError,
4645
Float64Index, _ensure_index)
4746
from pandas.core.indexing import check_bool_indexer, maybe_convert_indices
@@ -186,7 +185,7 @@ def __init__(self, data=None, index=None, dtype=None, name=None,
186185
index = Index(_try_sort(data))
187186

188187
try:
189-
data = index.get_values_from_dict(data)
188+
data = index._get_values_from_dict(data)
190189
except TypeError:
191190
data = ([data.get(i, nan) for i in index]
192191
if data else np.nan)

pandas/indexes/base.py

+10-7
Original file line numberDiff line numberDiff line change
@@ -2448,23 +2448,25 @@ def get_indexer_for(self, target, **kwargs):
24482448
indexer, _ = self.get_indexer_non_unique(target, **kwargs)
24492449
return indexer
24502450

2451-
def get_values_from_dict(self, input_dict):
2452-
"""Return the values of the input dictionary in the order the keys are
2451+
_index_shared_docs['_get_values_from_dict'] = """
2452+
Return the values of the input dictionary in the order the keys are
24532453
in the index. np.nan is returned for index values not in the
24542454
dictionary.
24552455
24562456
Parameters
24572457
----------
2458-
input_dict : dict
2458+
data : dict
24592459
The dictionary from which to extract the values
24602460
24612461
Returns
24622462
-------
2463-
Union[np.array, list]
2463+
np.array
24642464
24652465
"""
24662466

2467-
return lib.fast_multiget(input_dict, self.values,
2467+
@Appender(_index_shared_docs['_get_values_from_dict'])
2468+
def _get_values_from_dict(self, data):
2469+
return lib.fast_multiget(data, self.values,
24682470
default=np.nan)
24692471

24702472
def _possibly_promote(self, other):
@@ -2510,8 +2512,9 @@ def map(self, mapper):
25102512
25112513
Parameters
25122514
----------
2513-
mapper : Union[function, dict, Series]
2515+
mapper : {callable, dict, Series}
25142516
Function to be applied or input correspondence object.
2517+
dict and Series support new in 0.20.0.
25152518
25162519
Returns
25172520
-------
@@ -2528,7 +2531,7 @@ def map(self, mapper):
25282531
mapped_values = algos.take_1d(mapper.values, indexer)
25292532
elif isinstance(mapper, dict):
25302533
idx = Index(mapper.keys())
2531-
data = idx.get_values_from_dict(mapper)
2534+
data = idx._get_values_from_dict(mapper)
25322535
indexer = idx.get_indexer(self.values)
25332536
mapped_values = algos.take_1d(data, indexer)
25342537
else:

pandas/tests/indexes/test_base.py

+9-37
Original file line numberDiff line numberDiff line change
@@ -812,60 +812,32 @@ def test_map_tseries_indices_return_index(self):
812812
tm.assert_index_equal(exp, date_index.map(lambda x: x.hour))
813813

814814
def test_map_with_dict_and_series(self):
815+
# GH 12756
815816
expected = Index(['foo', 'bar', 'baz'])
816817
mapper = Series(expected.values, index=[0, 1, 2])
817-
tm.assert_index_equal(tm.makeIntIndex(3).map(mapper), expected)
818-
819-
# GH 12766
820-
# special = []
821-
special = ['catIndex']
822-
823-
for name in special:
824-
orig_values = ['a', 'B', 1, 'a']
825-
new_values = ['one', 2, 3.0, 'one']
826-
cur_index = CategoricalIndex(orig_values, name='XXX')
827-
expected = CategoricalIndex(new_values,
828-
name='XXX', categories=[3.0, 2, 'one'])
829-
830-
mapper = pd.Series(new_values[:-1], index=orig_values[:-1])
831-
output = cur_index.map(mapper)
832-
# Order of categories in output can be different
833-
tm.assert_index_equal(expected, output)
818+
result = tm.makeIntIndex(3).map(mapper)
819+
tm.assert_index_equal(result, expected)
834820

835-
mapper = {o: n for o, n in
836-
zip(orig_values[:-1], new_values[:-1])}
837-
output = cur_index.map(mapper)
838-
# Order of categories in output can be different
839-
tm.assert_index_equal(expected, output)
821+
for name in self.indices.keys():
822+
if name == 'catIndex':
823+
# Tested in test_categorical
824+
continue
840825

841-
for name in list(set(self.indices.keys()) - set(special)):
842826
cur_index = self.indices[name]
843827
expected = Index(np.arange(len(cur_index), 0, -1))
844828
mapper = pd.Series(expected, index=cur_index)
845829
tm.assert_index_equal(expected, cur_index.map(mapper))
846830

847831
mapper = {o: n for o, n in
848832
zip(cur_index, expected)}
833+
# If the mapper is empty the expected index type is Int64Index
834+
# but the output defaults to Float64 so I treat it independently
849835
if mapper:
850836
tm.assert_index_equal(expected, cur_index.map(mapper))
851837
else:
852-
# The expected index type is Int64Index
853-
# but the output defaults to Float64
854838
tm.assert_index_equal(Float64Index([]),
855839
cur_index.map(mapper))
856840

857-
def test_map_with_categorical_series(self):
858-
# GH 12756
859-
a = Index([1, 2, 3, 4])
860-
b = Series(["even", "odd", "even", "odd"],
861-
dtype="category")
862-
c = Series(["even", "odd", "even", "odd"])
863-
864-
exp = CategoricalIndex(["odd", "even", "odd", np.nan])
865-
tm.assert_index_equal(a.map(b), exp)
866-
exp = Index(["odd", "even", "odd", np.nan])
867-
tm.assert_index_equal(a.map(c), exp)
868-
869841
def test_map_with_non_function_missing_values(self):
870842
# GH 12756
871843
expected = Index([2., np.nan, 'foo'])

pandas/tests/indexes/test_category.py

+12
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,18 @@ def f(x):
239239
result = ci.map({'A': 10, 'B': 20, 'C': 30})
240240
tm.assert_index_equal(result, exp)
241241

242+
def test_map_with_categorical_series(self):
243+
# GH 12756
244+
a = pd.Index([1, 2, 3, 4])
245+
b = pd.Series(["even", "odd", "even", "odd"],
246+
dtype="category")
247+
c = pd.Series(["even", "odd", "even", "odd"])
248+
249+
exp = CategoricalIndex(["odd", "even", "odd", np.nan])
250+
tm.assert_index_equal(a.map(b), exp)
251+
exp = pd.Index(["odd", "even", "odd", np.nan])
252+
tm.assert_index_equal(a.map(c), exp)
253+
242254
def test_where(self):
243255
i = self.create_index()
244256
result = i.where(notnull(i))

pandas/tests/indexes/test_datetimelike.py

+36
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,42 @@ def test_view(self):
5252
result = self._holder(i)
5353
tm.assert_index_equal(result, i_view)
5454

55+
def test_map(self):
56+
# GH 12756
57+
idx = self.create_index()
58+
idx.name = 'foo'
59+
result = idx.map(lambda x: x + 1)
60+
expected = idx + 1
61+
tm.assert_index_equal(result, expected)
62+
63+
series_map = pd.Series(expected, idx)
64+
result = idx.map(series_map)
65+
tm.assert_index_equal(result, expected)
66+
67+
dict_map = {i: e for e, i in zip(expected, idx)}
68+
result = idx.map(dict_map)
69+
tm.assert_index_equal(result, expected)
70+
71+
# All empty maps to Float64Index
72+
empty_idx = Float64Index([np.nan for _ in range(len(idx))], name='foo')
73+
result = idx.map(pd.Series())
74+
tm.assert_index_equal(result, empty_idx)
75+
result = idx.map({})
76+
tm.assert_index_equal(result, empty_idx)
77+
78+
nat_expected = Index([pd.NaT] + [e for e in expected[1:]], name='foo')
79+
old_value = expected[0]
80+
81+
series_map.iloc[0] = pd.NaT
82+
series_map = pd.Series(old_value, [pd.NaT]).append(series_map)
83+
result = idx.map(series_map)
84+
tm.assert_index_equal(result, nat_expected)
85+
86+
dict_map.update({pd.NaT: old_value})
87+
dict_map[idx[0]] = pd.NaT
88+
result = idx.map(dict_map)
89+
tm.assert_index_equal(result, nat_expected)
90+
5591

5692
class TestDatetimeIndex(DatetimeLike, tm.TestCase):
5793
_holder = DatetimeIndex

pandas/tests/indexing/test_categorical.py

+18
Original file line numberDiff line numberDiff line change
@@ -405,3 +405,21 @@ def test_indexing_with_category(self):
405405

406406
res = (cat[['A']] == 'foo')
407407
tm.assert_frame_equal(res, exp)
408+
409+
def test_map_with_dict_or_series(self):
410+
orig_values = ['a', 'B', 1, 'a']
411+
new_values = ['one', 2, 3.0, 'one']
412+
cur_index = pd.CategoricalIndex(orig_values, name='XXX')
413+
expected = pd.CategoricalIndex(new_values,
414+
name='XXX', categories=[3.0, 2, 'one'])
415+
416+
mapper = pd.Series(new_values[:-1], index=orig_values[:-1])
417+
output = cur_index.map(mapper)
418+
# Order of categories in output can be different
419+
tm.assert_index_equal(expected, output)
420+
421+
mapper = {o: n for o, n in
422+
zip(orig_values[:-1], new_values[:-1])}
423+
output = cur_index.map(mapper)
424+
# Order of categories in output can be different
425+
tm.assert_index_equal(expected, output)

pandas/tseries/base.py

+8
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,14 @@ def __rsub__(self, other):
685685
def _add_delta(self, other):
686686
return NotImplemented
687687

688+
@Appender(_index_shared_docs['_get_values_from_dict'])
689+
def _get_values_from_dict(self, data):
690+
if len(data):
691+
return np.array([data.get(i, np.nan)
692+
for i in self.asobject.values])
693+
694+
return np.array([np.nan])
695+
688696
def _add_delta_td(self, other):
689697
# add a delta of a timedeltalike
690698
# return the i8 result view

pandas/tseries/index.py

+7-20
Original file line numberDiff line numberDiff line change
@@ -1380,29 +1380,16 @@ def get_value_maybe_box(self, series, key):
13801380
key, tz=self.tz)
13811381
return _maybe_box(self, values, series, key)
13821382

1383-
def get_values_from_dict(self, input_dict):
1384-
"""Return the values of the input dictionary in the order the keys are
1385-
in the index. np.nan is returned for index values not in the
1386-
dictionary.
1387-
1388-
Parameters
1389-
----------
1390-
input_dict : dict
1391-
The dictionary from which to extract the values
1392-
1393-
Returns
1394-
-------
1395-
Union[np.array, list]
1396-
1397-
"""
1398-
if len(input_dict):
1383+
@Appender(_index_shared_docs['_get_values_from_dict'])
1384+
def _get_values_from_dict(self, data):
1385+
if len(data):
13991386
# coerce back to datetime objects for lookup
1400-
input_dict = com._dict_compat(input_dict)
1401-
return lib.fast_multiget(input_dict,
1387+
data = com._dict_compat(data)
1388+
return lib.fast_multiget(data,
14021389
self.asobject.values,
14031390
default=np.nan)
1404-
else:
1405-
return np.nan
1391+
1392+
return np.array([np.nan])
14061393

14071394
def get_loc(self, key, method=None, tolerance=None):
14081395
"""

pandas/tseries/period.py

-19
Original file line numberDiff line numberDiff line change
@@ -783,25 +783,6 @@ def _get_unique_index(self, dropna=False):
783783
res = res.dropna()
784784
return res
785785

786-
def get_values_from_dict(self, input_dict):
787-
"""Return the values of the input dictionary in the order the keys are
788-
in the index. np.nan is returned for index values not in the
789-
dictionary.
790-
791-
Parameters
792-
----------
793-
input_dict : dict
794-
The dictionary from which to extract the values
795-
796-
Returns
797-
-------
798-
Union[np.array, list]
799-
800-
"""
801-
802-
return np.array([input_dict.get(i, np.nan) for i in self.values]
803-
if input_dict else [np.nan])
804-
805786
def get_loc(self, key, method=None, tolerance=None):
806787
"""
807788
Get integer location for requested label

pandas/tseries/tdi.py

-20
Original file line numberDiff line numberDiff line change
@@ -665,26 +665,6 @@ def get_value_maybe_box(self, series, key):
665665
values = self._engine.get_value(_values_from_object(series), key)
666666
return _maybe_box(self, values, series, key)
667667

668-
def get_values_from_dict(self, input_dict):
669-
"""Return the values of the input dictionary in the order the keys are
670-
in the index. np.nan is returned for index values not in the
671-
dictionary.
672-
673-
Parameters
674-
----------
675-
input_dict : dict
676-
The dictionary from which to extract the values
677-
678-
Returns
679-
-------
680-
Union[np.array, list]
681-
682-
"""
683-
684-
return np.array([input_dict.get(i, np.nan)
685-
for i in self.asobject.values]
686-
if input_dict else [np.nan])
687-
688668
def get_loc(self, key, method=None, tolerance=None):
689669
"""
690670
Get integer location for requested label

0 commit comments

Comments
 (0)