Python Pandas:.apply 需要永远?

jam*_*e_y 3 python machine-learning dataframe pandas

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

clicks['bought'] = clicks['session'].apply(getBoughtItemIDs)
Run Code Online (Sandbox Code Playgroud)

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

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

Ale*_*ley 5

有几件事使这段代码运行缓慢。

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

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

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

首先用于按“会话”中的值groupby对行进行分组buysapply用于连接每个值的字符串:

boughtSessions = buys.groupby('session')[col_to_join].apply(lambda x: ','.join(x))
Run Code Online (Sandbox Code Playgroud)

在哪里包含要连接在一起的值col_to_join的列buys

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

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

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

clicks['bought'] = clicks['session'].map(boughtSessions)
Run Code Online (Sandbox Code Playgroud)