将函数应用于 DataFrame 中的每个单元格

问题描述 投票:0回答:4

我有一个可能如下所示的数据框:

A        B        C
foo      bar      foo bar
bar foo  foo      bar

我想查看每行的每个元素(或每列的每个元素)并应用以下函数来获取后续数据帧:

def foo_bar(x):
    return x.replace('foo', 'wow')

应用该函数后,我的数据框将如下所示:

A        B        C
wow      bar      wow bar
bar wow  wow      bar

是否有一个简单的单行代码可以将函数应用于每个单元格?

这是一个简单的示例,因此除了应用函数之外,可能还有一种更简单的方法来执行这个特定示例,但我真正要问的是如何在数据帧内的每个单元格中应用函数。

python pandas dataframe function apply
4个回答
230
投票

您可以使用

applymap()
,这对于您的情况来说是简洁的。

df.applymap(foo_bar)

#     A       B       C
#0  wow     bar wow bar
#1  bar wow wow     bar

另一种选择是对函数进行向量化,然后使用

apply
方法:

import numpy as np
df.apply(np.vectorize(foo_bar))
#     A       B       C
#0  wow     bar wow bar
#1  bar wow wow     bar

3
投票

我想你可以使用

np.vectorize

>>> df[:] = np.vectorize(foo_bar)(df)
>>> df
       A    B    C
foo  bar  wow  bar
bar  wow  wow  bar
>>> 

这可能会更快,因为它使用的是

numpy


1
投票

扩展 Psidom 的答案,如果您定义的函数接受其他参数,那么您可以使用 kwargs 传递它们。例如,要在 OP 中切换

repl
foo_bar()

def foo_bar(x, bar=''):
    return x.replace('foo', bar)

df.applymap(foo_bar, bar='haha')

applymap
特别有用的常见情况之一是字符串操作(如OP中所示)。由于 pandas 中的字符串操作未进行优化,因此循环通常比向量化操作执行得更好,尤其是在有很多操作的情况下。例如,对于以下使用条件替换帧中的值的简单任务,
applymap
比等效的矢量化 Pandas 代码快 3 倍以上。

def foo_bar(x):
    return x.replace('foo', 'wow') if len(x)>3 else x + ' this'

df = pd.DataFrame([['foo', 'bar', 'foo bar'], ['bar foo', 'foo', 'bar']]*500000, columns=[*'ABC'])

%timeit df.applymap(foo_bar)
# 1.47 s ± 37.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit df.apply(lambda x: np.where(x.str.len()>3, x.str.replace('foo', 'wow'), x + ' this'))
# 4.64 s ± 597 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

0
投票

在 Pandas 的当前版本中,applymap 已弃用(自版本 2.1.0 起)。您可以使用 map 代替:

df.applymap(foo_bar)
© www.soinside.com 2019 - 2024. All rights reserved.