对 Pandas 数据框中的每一行只运行一次函数

Posted

技术标签:

【中文标题】对 Pandas 数据框中的每一行只运行一次函数【英文标题】:Run function exactly once for each row in a Pandas dataframe 【发布时间】:2016-08-05 04:50:39 【问题描述】:

如果我有一个功能

def do_irreversible_thing(a, b):
    print a, b

还有一个数据框,比如说

df = pd.DataFrame([(0, 1), (2, 3), (4, 5)], columns=['a', 'b'])

为 pandas 数据框中的每一行只运行一次函数的最佳方法是什么。 As 在其他 questions 中指出,类似 df.apply pandas 的东西会为第一行调用两次该函数。即使使用 numpy

np.vectorize(do_irreversible_thing)(df.a, df.b)

导致函数在第一行被调用两次,df.T.apply() 或 df.apply(..., axis=1) 也是如此。

有没有比这个显式循环更快或更简洁的方法来调用每一行的函数?

   for idx, a, b in df.itertuples():
       do_irreversible_thing(a, b)

【问题讨论】:

这听起来像是 for 循环的工作。通常没有很好的方法来矢量化副作用。 如果副作用不依赖于每一行的操作,那么它应该是可向量化的 如果您需要运行显式循环,使用zip(df.a, df.b)df.itertuples() 可能会获得更好的性能,详见this answer。 【参考方案1】:

我这样做的方式(因为我也不喜欢用 df.itertuples 循环的想法)是:

df.apply(do_irreversible_thing, axis=1)

然后你的函数应该是这样的:

def do_irreversible_thing(x):
    print x.a, x.b

这样你应该能够在每一行上运行你的函数。

如果你不能修改你的函数,你可以像这样apply

df.apply(lambda x: do_irreversible_thing(x[0],x[1]), axis=1)

【讨论】:

【参考方案2】:

目前尚不清楚您的函数在做什么,但您可以通过将axis=1 传递给apply 您的函数逐行传递并传递感兴趣的列元素来向每一行传递apply 一个函数:

In [155]:
def foo(a,b):
    return a*b
​
df = pd.DataFrame([(0, 1), (2, 3), (4, 5)], columns=['a', 'b'])
df.apply(lambda x: foo(x['a'], x['b']), axis=1)

Out[155]:
0     0
1     6
2    20
dtype: int64

但是,只要您的函数不依赖于每行上的 df 变异,那么您可以只使用矢量化方法对整个列进行操作:

In [156]:
df['a'] * df['b']

Out[156]:
0     0
1     6
2    20
dtype: int64

原因是因为函数是矢量化的,所以它会更好地扩展,而 apply 只是用于迭代你的 df 的语法糖,所以它本质上是一个 for 循环

【讨论】:

以上是关于对 Pandas 数据框中的每一行只运行一次函数的主要内容,如果未能解决你的问题,请参考以下文章

为数据框中的每一行应用一个函数,用于另一个数据框中的每一行

在Pandas中,我如何将一个函数应用到数据框的某一行,其中行中的每一项都应该作为参数传递给函数?

对 pandas 数据框中的列使用 map()

将函数应用于pandas Python中的每一行时出现数据转换错误

将邮政编码 API 调用应用于数据框中的每一行

将数据框中的每一行除以 Python 中的向量