40

Why doesn't df.index.map(dict) work like df['column_name'].map(dict)?

Here's a little example of trying to use index.map:

import pandas as pd

df = pd.DataFrame({'one': {'A': 10, 'B': 20, 'C': 30, 'D': 40, 'E': 50}})
map_dict = {'A': 'every', 'B': 'good', 'C': 'boy', 'D': 'does', 'E': 'fine'}
df
'''
    one
A   10
B   20
C   30
D   40
E   50
'''

df['two'] = df.index.map(mapper=map_dict)

This raises TypeError: 'dict' object is not callable

Feeding it a lambda works:

df['two'] = df.index.map(mapper=(lambda x: map_dict[x])); df
'''
   one    two
A   10  every
B   20   good
C   30    boy
D   40   does
E   50   fine
'''

However, resetting the index and mapping on a column works as expected without complaint:

df.reset_index(inplace=True)
df.rename(columns={'index': 'old_ndx'}, inplace=True) #so there's no index name confusion
df['two'] = df.old_ndx.map(map_dict); df

'''
  old_ndx  one    two
0       A   10  every
1       B   20   good
2       C   30    boy
3       D   40   does
4       E   50   fine
'''
2
  • 2
    According to the docs, pandas.Index.map requires a callable. Is your question why was this design decision made? Commented Apr 11, 2017 at 21:47
  • 2
    Here is a relevant issue. It seems it's just something that slipped through the cracks, that they haven't gotten around to fixing. It seems that it is currently being remedied. Commented Apr 11, 2017 at 21:51

6 Answers 6

47

I'm not answering your question... Just giving you a better work around.
Use to_series() them map

df = pd.DataFrame({'one': {'A': 10, 'B': 20, 'C': 30, 'D': 40, 'E': 50}})
map_dict = {'A': 'every', 'B': 'good', 'C': 'boy', 'D': 'does', 'E': 'fine'}

df['two'] = df.index.to_series().map(map_dict)

df

   one    two
A   10  every
B   20   good
C   30    boy
D   40   does
E   50   fine
Sign up to request clarification or add additional context in comments.

Comments

24

Adding get at the end

df['Two']=df.index.map(map_dict.get)
df
Out[155]: 
   one    Two
A   10  every
B   20   good
C   30    boy
D   40   does
E   50   fine

5 Comments

@Nitin it will loop via every single index look up the key to find the value in the dict
Sorry, I meant like why does the .get method make the code work, as opposed to just the dictionary
@Nitin base on pandas doc pandas.pydata.org/pandas-docs/stable/generated/…, it only accpet mapper function not dict or Serise .
Weird. I hadn’t upvoted this. Well, problem solved.
doesnt seem necessary as of 2022. df.index.map(dict) works for me
16

As of pandas version 0.23.x (released at May 15th, 2018) this problem is fixed:

import pandas as pd
pd.__version__        # 0.23.4

df = pd.DataFrame({'one': {'A': 10, 'B': 20, 'C': 30, 'D': 40, 'E': 50}})
map_dict = {'A': 'every', 'B': 'good', 'C': 'boy', 'D': 'does', 'E': 'fine'}
df
#    one
# A   10
# B   20
# C   30
# D   40
# E   50
df.index.map(map_dict)
#        one
# every   10
# good    20
# boy     30
# does    40
# fine    50

From the What's New page for pandas 0.23.0 it says:

Index.map() can now accept Series and dictionary input objects (GH12756, GH18482, GH18509).

For more information, check the help page of Index.map

Comments

6

An alternative workaround to calling map:

df['two'] = pd.Series(map_dict)

df

   one    two
A   10  every
B   20   good
C   30    boy
D   40   does
E   50   fine

In any case, until the mapping issue gets resolved (per juanpa.arrivillaga's comment) you have to convert either the index or the dict-to-map to a pandas Series.

Comments

4

A shorter alternative --with no explicit call to to_series or pd.Series:

df['two'] = df.rename(map_dict).index

Comments

1

map (a python keyword) is apparently being used as a method of df.index

Because this has its own internal demands, passing it an argument which has no __call__ method is not allowed.

lambda and functions are callable, a simple test:

def foo():
    pass
if foo.__call__:
    print True
# Prints True

bar = lambda x: x+1
if bar.__call__:
    print True
# Prints True

print {'1':'one'}.__call__
# AttributeError: 'dict' object has no attribute '__call__'

1 Comment

map isn't being "overridden". map is a function, not a method, so there is nothing to override.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.