传递字典时映射vs applymap

时间:2015-05-27 15:51:15

标签: python pandas

我认为我很了解地图与应用地图,但遇到了问题(如果感兴趣,请参阅here了解其他背景信息。)

一个简单的例子:

df  = pd.DataFrame( [[1,2],[1,1]] ) 
dct = { 1:'python', 2:'gator' }

df[0].map( lambda x: x+90 )
df.applymap( lambda x: x+90 )

按预期工作 - 两者都以元素为基础,在一个系列上映射,在数据帧上应用地图(非常好地解释here btw)。

如果我使用字典而不是lambda,地图仍然可以正常工作:

df[0].map( dct )

0    python
1    python

但不是applymap:

df.applymap( dct )
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-100-7872ff604851> in <module>()
----> 1 df.applymap( dct )

C:\Users\johne\AppData\Local\Continuum\Anaconda\lib\site-packages\pandas\core\frame.pyc in applymap(self, func)
   3856                 x = lib.map_infer(_values_from_object(x), f)
   3857             return lib.map_infer(_values_from_object(x), func)
-> 3858         return self.apply(infer)
   3859 
   3860     #----------------------------------------------------------------------

C:\Users\johne\AppData\Local\Continuum\Anaconda\lib\site-packages\pandas\core\frame.pyc in apply(self, func, axis, broadcast, raw, reduce, args, **kwds)
   3687                     if reduce is None:
   3688                         reduce = True
-> 3689                     return self._apply_standard(f, axis, reduce=reduce)
   3690             else:
   3691                 return self._apply_broadcast(f, axis)

C:\Users\johne\AppData\Local\Continuum\Anaconda\lib\site-packages\pandas\core\frame.pyc in _apply_standard(self, func, axis, ignore_failures, reduce)
   3777             try:
   3778                 for i, v in enumerate(series_gen):
-> 3779                     results[i] = func(v)
   3780                     keys.append(v.name)
   3781             except Exception as e:

C:\Users\johne\AppData\Local\Continuum\Anaconda\lib\site-packages\pandas\core\frame.pyc in infer(x)
   3855                 f = com.i8_boxer(x)
   3856                 x = lib.map_infer(_values_from_object(x), f)
-> 3857             return lib.map_infer(_values_from_object(x), func)
   3858         return self.apply(infer)
   3859 

C:\Users\johne\AppData\Local\Continuum\Anaconda\lib\site-packages\pandas\lib.pyd in pandas.lib.map_infer (pandas\lib.c:56990)()

TypeError: ("'dict' object is not callable", u'occurred at index 0')

所以,我的问题是为什么这里不能以类似的方式映射和应用地图?这是applymap的错误,还是我做错了什么?

编辑添加:我发现我可以通过以下方式轻松解决此问题:

df.applymap( lambda x: dct[x] )

        0       1
0  python   gator
1  python  python

或者更好的是通过这个answer不需要lambda。

df.applymap( dct.get )

这几乎完全等同,对吧?必须是applymap如何解析语法的东西,我想函数/方法的显式形式比字典更好。无论如何,我想现在这里没有任何实际问题,但如果有人想回答,我仍然对这里发生的事情感兴趣。

1 个答案:

答案 0 :(得分:5)

.applymap()和.map()在元素方面是正确的。但.applymap()不会占用每一列,而是对这些列执行.map(),但每个列都执行.apply()。

所以当你调用df.applymap(dct)时: 发生的事情是df [0] .apply(dct),而不是df [0] .map(dct)

这里有两个系列方法之间的区别:

.map()接受Series,dict和function(任何可调用的,所以像dict.get这样的方法也可以作为第一个参数); as .apply()只接受函数(或任何可调用的)作为第一个参数。

.map()包含if语句,用于确定传递的第一个参数是dict,Series还是函数,并根据输入进行操作。将函数传递给.map()时,.map()方法执行与.apply()相同的操作。

但.apply()没有那些允许它与dictionnary和Series完全交易的if语句。它只知道如何使用callable。

当你用一个函数调用.apply()或.map()时,它们都会调用lib.map_infer(),它看起来像是python的map()函数(但我可以把手放在源代码,所以我不完全确定。)

执行map(dct,df [0])将给出与df.applymap(dct)和df [0]相同的错误.apply(dct)也会出现相同的错误。

现在,您可以问为什么使用.apply()而不是.map(),如果.map()在使用函数调用时执行相同的操作并且可以使用dict和Series?

因为.apply()可以返回一个Dataframe,如果传递给它的函数的结果是Series。

ser = pandas.Series([1,2,3,4,5], index=range(5))

ser_map = ser.map(lambda x : pandas.Series([x]*5, index=range(5)))
type(ser_map)
pandas.core.series.Series

ser_app = ser.apply(lambda x : pandas.Series([x]*5, index=range(5)))
type(ser_app)
pandas.core.frame.DataFrame