【问题标题】:Run function exactly once for each row in a Pandas dataframe对 Pandas 数据框中的每一行只运行一次函数
【发布时间】: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

标签: python function numpy pandas


【解决方案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 循环

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-29
      • 2022-12-16
      相关资源
      最近更新 更多