当前位置: 首页>>技术问答>>正文


python – Pandas中map,applymap和apply方法之间的区别

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)上按元素执行。

全面的差异对比

mapapplymapapply的比较:上下文相关

第一个主要区别:定义

  • map仅在Series(系列)上定义
  • applymap仅在DataFrame上定义
  • apply在Series和DataFrame两者上均有定义

第二个主要区别:输入参数

  • map接受dictSeries或可调用的函数对象
  • applymapapply仅接受可调用函数对象

第三大区别:行为

  • 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(脚注)

  1. 传入字典/系列参数时,map将基于该字典/系列中的键来映射元素。缺少的值将在输出中记录为NaN。
  2. 最新版本中的applymap已针对某些操作进行了优化。在某些情况下,您会发现applymap的速度比apply速度稍快。我的建议是对它们都进行测试,并使用更好的方法。
  3. map针对元素映射和转换进行了优化。涉及字典或系列的操作将使Panda是能够使用更快的代码路径来获得更好的性能。
  4. Series.apply返回用于聚合操作的标量,或者返回Series。对于DataFrame.apply来说也一样。请注意,当通过某些NumPy函数(例如均值,总和等)调用apply时,apply也具有快速路径。

补充的知识点

Series.applySeries.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) 


 

参考资料

 

本文由《纯净天空》出品。文章地址: https://vimsky.com/article/4360.html,未经允许,请勿转载。