Pandas中有map,还有applymap和apply方法/函数,它们之间有什么区别?
简单示例比较
我们知道map是Series方法,另外2个是的是DataFrame方法。容易让人困惑的是apply和applymap方法——为什么我们有两种方法将函数应用于DataFrame?
我们看看来自韦斯·麦金尼(Wes McKinney)的Python for Data Analysis书的解释,第132页。(强烈推荐这本书):
Another frequent operation is applying a function on 1D arrays to each column or row. DataFrame’s apply method does exactly this:
译文:另一常见操作是将一维数组上的函数应用于每一列或每一行。 DataFrame的apply方法正是这样做的:
In [116]: frame = DataFrame(np.random.randn(4, 3), columns=list('bde'), index=['Utah', 'Ohio', 'Texas', 'Oregon'])
In [117]: frame
Out[117]:
b d e
Utah -0.029638 1.081563 1.280300
Ohio 0.647747 0.831136 -1.549481
Texas 0.513416 -0.884417 0.195343
Oregon -0.485454 -0.477388 -0.309548
In [118]: f = lambda x: x.max() - x.min()
In [119]: frame.apply(f)
Out[119]:
b 1.133201
d 1.965980
e 2.829781
dtype: float64
Many of the most common array statistics (like sum and mean) are DataFrame methods, so using apply is not necessary.
Element-wise Python functions can be used, too. Suppose you wanted to compute a formatted string from each floating point value in frame. You can do this with applymap:
译文:许多最常见的数组统计信息(例如sum和mean)用DataFrame内置方法就可以实现, 当然也可以使用基于元素的Python函数,所以做这些计算的话apply并不是必须的。假设您要根据DataFrame中的每个浮点值来计算格式化的字符串,您可以使用applymap做到这一点:
In [120]: format = lambda x: '%.2f' % x
In [121]: frame.applymap(format)
Out[121]:
b d e
Utah -0.03 1.08 1.28
Ohio 0.65 0.83 -1.55
Texas 0.51 -0.88 0.20
Oregon -0.49 -0.48 -0.31
The reason for the name applymap is that Series has a map method for applying an element-wise function:
译文:之所以使用applymap作为名称,是因为Series具有用于应用逐元素函数的map方法:
In [122]: frame['e'].map(format)
Out[122]:
Utah 1.28
Ohio -1.55
Texas 0.20
Oregon -0.31
Name: e, dtype: object
总结起来,apply在DataFrame的行/列上执行,applymap在DataFrame的元素上执行,map在系列数据(Series)上按元素执行。
全面的差异对比
map,applymap和apply的比较:上下文相关
第一个主要区别:定义
map仅在Series(系列)上定义
applymap仅在DataFrame上定义
apply在Series和DataFrame两者上均有定义
第二个主要区别:输入参数
map接受dict,Series或可调用的函数对象
applymap和apply仅接受可调用函数对象
第三大区别:行为
map是对Series按元素操作的
applymap是对DataFrames按元素操作的
apply也可以逐元素运行,但适用于更复杂的操作和聚合。行为和返回值取决于函数。
第四大区别(最重要的区别):用例
map用于将值从一个域映射到另一个域,因此针对性能进行了优化(例如df['A'].map({1:'a', 2:'b', 3:'c'}))
applymap适用于跨多个行/列的元素转换(例如df[['A', 'B', 'C']].applymap(str.strip))
apply用于应用无法向量化的任何功能(例如df['sentences'].apply(nltk.sent_tokenize))
小结
Footnotes(脚注)
传入字典/系列参数时,map将基于该字典/系列中的键来映射元素。缺少的值将在输出中记录为NaN。
最新版本中的applymap已针对某些操作进行了优化。在某些情况下,您会发现applymap的速度比apply速度稍快。我的建议是对它们都进行测试,并使用更好的方法。
map针对元素映射和转换进行了优化。涉及字典或系列的操作将使Panda是能够使用更快的代码路径来获得更好的性能。
Series.apply返回用于聚合操作的标量,或者返回Series。对于DataFrame.apply来说也一样。请注意,当通过某些NumPy函数(例如均值,总和等)调用apply时,apply也具有快速路径。
补充的知识点
Series.apply和Series.map的功能之间有很多重叠之处,这意味着在大多数情况下任何一种都可以使用。但是,它们确实有一些细微的差异,参考下面的对比示例,map只会将一个系列放在另一个系列的每个单元格中,这可能不是您想要的。
In [40]: p=pd.Series([1,2,3])
In [41]: p
Out[31]:
0 1
1 2
2 3
dtype: int64
In [42]: p.apply(lambda x: pd.Series([x, x]))
Out[42]:
0 1
0 1 1
1 2 2
2 3 3
In [43]: p.map(lambda x: pd.Series([x, x]))
Out[43]:
0 0 1
1 1
dtype: int64
1 0 2
1 2
dtype: int64
2 0 3
1 3
dtype: int64
dtype: object
另外,如果我有一个带有副作用的函数,例如“连接到Web服务器”,则可能为了清楚起见,我可能会使用apply。
series.apply(download_file_for_every_element)
参考资料