You need (self, key) as the arguments for __missing__:
class MyDict(dict):
def __missing__(self, key):
return "_Unknown"
import pandas as pd
s = pd.Series(range(4))
d = {0: 'foo', 1: 'bar', 2: 'baz'}
s.map(MyDict(d))
#0 foo
#1 bar
#2 baz
#3 _Unknown
#dtype: object
And while this functionality is nice, map is a very efficient pandas method when it uses standard dictionaries, the above will slow it down (shown below). So instead you can map with a normal dict then chain on a .fillna to handle the default.
s.map(d).fillna('_Unknown')
#0 foo
#1 bar
#2 baz
#3 _Unknown
#dtype: object
Illustrations of the timings using a dictionary with a special return for missing keys versus a normal dictionary followed by a .fillna. MyDict is a lot faster for very small mappings, but is slower for larger Series.
import perfplot
import pandas as pd
import numpy as np
class MyDict(dict):
def __missing__(self, key):
return "_Unknown"
d = {0: 'foo', 1: 'bar', 2: 'baz'}
d2 = MyDict(d)
def map_fillna(s, d):
return s.map(d).fillna("_Unknown")
def use_MyDict(s, MyDict):
return s.map(MyDict)
perfplot.show(
setup=lambda n: pd.Series(np.random.choice(range(7), n)),
kernels=[
lambda s: map_fillna(s, d),
lambda s: use_MyDict(s, d2),
],
labels=['map + fillna', 'MyDict'],
n_range=[2 ** k for k in range(1, 27)],
equality_check= lambda x,y: x.compare(y).empty,
xlabel='len(s)'
)
