|
12 | 12 | is_object_dtype,
|
13 | 13 | is_list_like,
|
14 | 14 | is_scalar,
|
15 |
| - is_datetimelike) |
| 15 | + is_datetimelike, |
| 16 | + is_extension_type) |
16 | 17 |
|
17 | 18 | from pandas.util._validators import validate_bool_kwarg
|
18 | 19 |
|
19 |
| -from pandas.core import common as com |
| 20 | +from pandas.core import common as com, algorithms |
20 | 21 | import pandas.core.nanops as nanops
|
21 | 22 | import pandas._libs.lib as lib
|
22 | 23 | from pandas.compat.numpy import function as nv
|
@@ -838,6 +839,78 @@ def _reduce(self, op, name, axis=0, skipna=True, numeric_only=None,
|
838 | 839 | klass=self.__class__.__name__, op=name))
|
839 | 840 | return func(**kwds)
|
840 | 841 |
|
| 842 | + def _map_values(self, mapper, na_action=None): |
| 843 | + """An internal function that maps values using the input |
| 844 | + correspondence (which can be a dict, Series, or function). |
| 845 | +
|
| 846 | + Parameters |
| 847 | + ---------- |
| 848 | + mapper : function, dict, or Series |
| 849 | + The input correspondence object |
| 850 | + na_action : {None, 'ignore'} |
| 851 | + If 'ignore', propagate NA values, without passing them to the |
| 852 | + mapping function |
| 853 | +
|
| 854 | + Returns |
| 855 | + ------- |
| 856 | + applied : Union[Index, MultiIndex], inferred |
| 857 | + The output of the mapping function applied to the index. |
| 858 | + If the function returns a tuple with more than one element |
| 859 | + a MultiIndex will be returned. |
| 860 | +
|
| 861 | + """ |
| 862 | + |
| 863 | + # we can fastpath dict/Series to an efficient map |
| 864 | + # as we know that we are not going to have to yield |
| 865 | + # python types |
| 866 | + if isinstance(mapper, dict): |
| 867 | + if hasattr(mapper, '__missing__'): |
| 868 | + # If a dictionary subclass defines a default value method, |
| 869 | + # convert mapper to a lookup function (GH #15999). |
| 870 | + dict_with_default = mapper |
| 871 | + mapper = lambda x: dict_with_default[x] |
| 872 | + else: |
| 873 | + # Dictionary does not have a default. Thus it's safe to |
| 874 | + # convert to an Series for efficiency. |
| 875 | + # we specify the keys here to handle the |
| 876 | + # possibility that they are tuples |
| 877 | + from pandas import Series |
| 878 | + mapper = Series(mapper, index=mapper.keys()) |
| 879 | + |
| 880 | + if isinstance(mapper, ABCSeries): |
| 881 | + # Since values were input this means we came from either |
| 882 | + # a dict or a series and mapper should be an index |
| 883 | + if is_extension_type(self.dtype): |
| 884 | + values = self._values |
| 885 | + else: |
| 886 | + values = self.values |
| 887 | + |
| 888 | + indexer = mapper.index.get_indexer(values) |
| 889 | + new_values = algorithms.take_1d(mapper._values, indexer) |
| 890 | + |
| 891 | + return new_values |
| 892 | + |
| 893 | + # we must convert to python types |
| 894 | + if is_extension_type(self.dtype): |
| 895 | + values = self._values |
| 896 | + if na_action is not None: |
| 897 | + raise NotImplementedError |
| 898 | + map_f = lambda values, f: values.map(f) |
| 899 | + else: |
| 900 | + values = self.astype(object) |
| 901 | + values = getattr(values, 'values', values) |
| 902 | + if na_action == 'ignore': |
| 903 | + def map_f(values, f): |
| 904 | + return lib.map_infer_mask(values, f, |
| 905 | + isna(values).view(np.uint8)) |
| 906 | + else: |
| 907 | + map_f = lib.map_infer |
| 908 | + |
| 909 | + # mapper is a function |
| 910 | + new_values = map_f(values, mapper) |
| 911 | + |
| 912 | + return new_values |
| 913 | + |
841 | 914 | def value_counts(self, normalize=False, sort=True, ascending=False,
|
842 | 915 | bins=None, dropna=True):
|
843 | 916 | """
|
|
0 commit comments