只是为了获得更多的上下文和直觉,这里有一个明确而具体的差异示例。
假设您有如下所示的以下功能。 (
此标签功能将根据您作为参数 (x) 提供的阈值将值任意拆分为“高”和“低”。 )
def label(element, x):
if element > x:
return 'High'
else:
return 'Low'
在这个例子中,假设我们的数据框有一列带有随机数。
如果您尝试使用 map 映射标签函数:
df['ColumnName'].map(label, x = 0.8)
您将得到以下错误:
TypeError: map() got an unexpected keyword argument 'x'
现在使用同样的函数并使用apply,你会发现它起作用了:
df['ColumnName'].apply(label, x=0.8)
Series.apply() 可以按元素接受额外的参数,而 Series.map() 方法将返回错误。
现在,如果您尝试将相同的函数同时应用于数据框中的多个列,则使用 DataFrame.applymap()。
df[['ColumnName','ColumnName2','ColumnName3','ColumnName4']].applymap(label)
最后,您也可以在数据帧上使用 apply() 方法,但 DataFrame.apply() 方法具有不同的功能。 df.apply() 方法不是按元素应用函数,而是沿轴应用函数,按列或按行。当我们创建一个与 df.apply() 一起使用的函数时,我们将其设置为接受一个系列,最常见的是一个列。
这是一个例子:
df.apply(pd.value_counts)
当我们将 pd.value_counts 函数应用于数据帧时,它会计算所有列的值计数。
注意,当我们使用 df.apply() 方法来转换多个列时,这一点非常重要。这仅是可能的,因为 pd.value_counts 函数对序列进行操作。如果我们尝试使用 df.apply() 方法将一个按元素工作的函数应用于多个列,我们会得到一个错误:
例如:
def label(element):
if element > 1:
return 'High'
else:
return 'Low'
df[['ColumnName','ColumnName2','ColumnName3','ColumnName4']].apply(label)
这将导致以下错误:
ValueError: ('The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().', u'occurred at index Economy')
一般来说,我们应该只在向量化函数不存在时使用 apply() 方法。回想一下,pandas 使用矢量化(一次将操作应用于整个系列的过程)来优化性能。当我们使用 apply() 方法时,我们实际上是在循环遍历行,因此向量化的方法可以比 apply() 方法更快地执行等效任务。
以下是一些您不想使用任何类型的应用/映射方法重新创建的矢量化函数示例:
- Series.str.split() 拆分系列中的每个元素
- Series.str.strip() 从 Series 中的每个字符串中去除空格。
- Series.str.lower() 将 Series 中的字符串转换为小写。
- Series.str.upper() 将 Series 中的字符串转换为大写。
- Series.str.get() 检索 Series 中每个元素的第 i 个元素。
- Series.str.replace() 用另一个字符串替换系列中的正则表达式或字符串
- Series.str.cat() 将字符串连接到一个系列中。
- Series.str.extract() 从与正则表达式模式匹配的系列中提取子字符串。