Python Pandas:.apply 需要永远吗?

Posted

技术标签:

【中文标题】Python Pandas:.apply 需要永远吗?【英文标题】:Python Pandas: .apply taking forever? 【发布时间】:2015-05-17 18:30:32 【问题描述】:

我有一个通过解析大小为 1.4G 的 CSV 创建的 DataFrame 'clicks'。我正在尝试使用 apply 函数创建一个“购买”的新列。

clicks['bought'] = clicks['session'].apply(getBoughtItemIDs)

在 getBoughtItemIDs 中,我正在检查 'buys' 数据框是否有我想要的值,如果有,则返回一个连接它们的字符串。 getBoughtItemIDs 中的第一行将永远占用。有什么方法可以加快速度?

def getBoughtItemIDs(val):
  boughtSessions = buys[buys['session'] == val].values
  output = ''
  for row in boughtSessions:
    output += str(row[1]) + ","
  return output

【问题讨论】:

【参考方案1】:

有几件事会导致此代码运行缓慢。

apply 本质上只是for 在列的行上循环的语法糖。在你的函数中还有一个显式的 for 循环遍历 NumPy 数组(for row in boughtSessions 部分)。最好尽可能避免以这种(非矢量化)方式循环,因为它会严重影响性能。

buys[buys['session'] == val].values 正在为clicks 的每一行在整个列中查找val然后返回一个子数据帧然后创建一个新的 NumPy 数组。以这种方式重复查找值是昂贵的(O(n) 每次查找的复杂性)。创建新数组会很昂贵,因为每次都必须分配内存并复制数据。

如果我理解您想要做什么,您可以尝试以下方法来获取您的新专栏。

首先使用groupbybuys 的行按“会话”中的值分组。 apply 用于连接每个值的字符串:

boughtSessions = buys.groupby('session')[col_to_join].apply(lambda x: ','.join(x))

其中col_to_join 是来自buys 的列,其中包含您要连接到一个字符串中的值。

groupby 意味着只需要一次通过 DataFrame,并且在 Pandas 中得到了很好的优化。此处使用apply 连接字符串是不可避免的,但只需要通过分组值。

boughtSessions 现在是由“会话”列中的唯一值索引的一系列字符串。这很有用,因为查找 Pandas 索引的复杂度是 O(1)

要将boughtSessions 中的每个字符串与clicks['session'] 中的方法值匹配,您可以使用map。与apply 不同,map 是完全矢量化的,应该非常快:

clicks['bought'] = clicks['session'].map(boughtSessions)

【讨论】:

以上是关于Python Pandas:.apply 需要永远吗?的主要内容,如果未能解决你的问题,请参考以下文章

在apply函数pandas python中包含组名

Python Pandas:“numpy.ndarray”对象没有属性“apply”

Python Pandas - 带有 apply() 和 rolling() 的 groupby() 非常慢

Python pandas:我们可以避免在 groupby/apply 这种情况下应用吗?

Python Pandas:如何在不编写辅助函数的情况下使用 apply 广播操作

Pandas文摘:Applying Operations Over pandas Dataframes