在DataFrame中对每个单元格应用函数

155

我有一个数据框可能看起来像这样:

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

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

这只是一个简单的例子,因此可能有比应用函数更容易执行此特定示例的方法,但我真正想问的是如何在数据帧中的每个单元格中应用函数。

3个回答

228
你可以使用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

Pandas中map、applymap和apply方法的区别 - Franck Dernoncourt

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中切换foo_bar()repl

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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接