我以为我比较了解 map 和套用 map ,但是遇到了问题(如果有兴趣,请参阅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 )
可以按预期工作-两者都在元素基础上运行,在系列上进行映射,在数据帧上进行applymap(很好地解释了here btw)。
如果我使用字典而不是lambda,则 map 仍然可以正常运行:
df[0].map( dct )
0 python
1 python
但不套用map:
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不能以类似的方式工作?这是applymap的错误,还是我做错了什么?
编辑以添加:我发现我可以使用以下方法轻松解决此问题:
df.applymap( lambda x: dct[x] )
0 1
0 python gator
1 python python
或通过此answer更好,它不需要lambda。
df.applymap( dct.get )
这几乎是完全等效的,对不对?必须与applymap如何解析语法有关,我想函数/方法的显式形式比字典更好。无论如何,我想现在这里没有实际的问题了,但是如果有人想回答,我仍然对这里发生的事情感兴趣。
最佳答案
.applymap()和.map()对于按元素工作是正确的。但是.applymap()不会占用所有列并在它们上执行.map(),但会在每个列上执行.apply()。
因此,当您调用df.applymap(dct)时:
发生的是df [0] .apply(dct),而不是df [0] .map(dct)
这两个Series方法之间的区别是什么:
.map()接受系列,字典和函数(任何可调用的,因此像dict.get这样的方法也可以)作为第一个参数; as .apply()仅接受函数(或任何可调用的函数)作为第一个参数。
.map()包含if语句,以判断传递的第一个参数是dict,Series还是函数,并根据输入正确执行操作。当您将函数传递给.map()时,.map()方法的作用与.apply()相同。
但是.apply()没有那些允许它正确处理dictionnary和Series的if语句。它只知道如何与可调用对象一起工作。
当您使用函数调用.apply()或.map()时,它们都将终止调用lib.map_infer(),它们看起来像是python的map()函数(但Im可以将手放在源代码上,我不能完全确定)。
进行map(dct,df [0])将给您与df.applymap(dct)相同的错误,而df [0] .apply(dct)也将给您相同的错误。
现在,您可以问为什么使用.apply()而不是.map()了,如果.map()在通过函数调用时做相同的事情并且可以接受dict和Series?
因为.apply()如果传递给它的函数的结果是Series,则可以返回一个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