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)
每次查找的复杂性)。创建新数组会很昂贵,因为每次都必须分配内存并复制数据。
如果我理解您想要做什么,您可以尝试以下方法来获取您的新专栏。
首先使用groupby
将buys
的行按“会话”中的值分组。 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 需要永远吗?的主要内容,如果未能解决你的问题,请参考以下文章
Python Pandas:“numpy.ndarray”对象没有属性“apply”
Python Pandas - 带有 apply() 和 rolling() 的 groupby() 非常慢
Python pandas:我们可以避免在 groupby/apply 这种情况下应用吗?