当传递字典时,Map与Applymap的区别

10

我本以为我对map和applymap的理解很好,但现在遇到了问题(如果您感兴趣,请查看这里获取更多背景信息)。

一个简单的例子:

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 )

这个结果如预期一样 -- 两者都是基于元素操作的,map用在series上,applymap用在dataframe上(在这里很好地解释了 这里)。

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

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')

所以,我的问题是为什么map和applymap在这里不能像类似的方式工作?这是applymap的一个bug吗,还是我做错了什么?
编辑添加:我已经发现可以通过以下方法轻松解决这个问题:
df.applymap( lambda x: dct[x] )

        0       1
0  python   gator
1  python  python

更好的方法是通过这个答案,不需要使用lambda。

df.applymap( dct.get )

所以这两种方法基本上是完全等价的,对吧?可能是applymap函数解析语法的方式有些问题,使用函数或方法形式比字典更好。无论如何,现在似乎已经没有实际问题了,但如果有人想回答这里发生了什么,我仍然很感兴趣。


1
df.applymap()方法不能在DataFrame的每个Series上应用.map()方法,应该在每个Series上使用map .apply()方法。请参阅此处的Series .apply()方法: link 而.apply()需要一个函数作为参数,而不能像.map()一样接受一个字典。 - Data_addict
1
抱歉,我真的不明白你在这里说什么。 我猜applymap和map不等同,这一点我不争议,但我对其原因或如何发生没有更好的理解。引用上面链接(一个非常受欢迎的SO答案)中的话:“applymap在DataFrame上逐元素工作,而map在Series上逐元素工作。” 我希望对该观点有所阐述。 - JohnE
1个回答

6

.applymap()和.map()都是按元素逐一处理的。但是.applymap()不会接受每一列并在其上执行.map(),而是对每一列执行.apply()。

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

以下是这两种Series方法之间的区别:

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

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

但是.apply()没有这些if语句,无法正确处理字典和Series。它只知道如何使用可调用对象。

当您使用函数调用.apply()或.map()时,它们都最终调用lib.map_infer(),该函数看起来像Python的map()函数(但我无法找到源代码,因此不完全确定)。

使用map(dct, df[0])将会产生与df.applymap(dct)相同的错误,而df[0].apply(dct)也将产生相同的错误。

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

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

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

谢谢!这个例子展示了map如何生成一个Series,apply如何生成一个DataFrame,并解释了我之前得到但不理解的一些结果。我对所有这些的理解仍然不到100%,但这有所帮助。 - JohnE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接