我有一个DataFrame'点击'通过解析大小为1.4G的CSV创建。我试图创建一个新专栏' buy'使用应用功能。
clicks['bought'] = clicks['session'].apply(getBoughtItemIDs)
在getBoughtItemIDs中,我正在检查是否购买' dataframe具有我想要的值,如果是,则返回连接它们的字符串。 getBoughtItemIDs的第一行是永远的。有什么方法可以让它更快?
def getBoughtItemIDs(val):
boughtSessions = buys[buys['session'] == val].values
output = ''
for row in boughtSessions:
output += str(row[1]) + ","
return output
答案 0 :(得分:3)
有几件事使这段代码运行缓慢。
apply
基本上只是一行for
循环的语法糖。在函数中的NumPy数组(for
部分)上还有一个明确的for row in boughtSessions
循环。尽可能避免以这种(非矢量化)方式循环,因为它会严重影响性能。
buys[buys['session'] == val].values
在val
的每一行的整个列中查找clicks
,然后返回子DataFrame 和然后创建一个新的NumPy数组。以这种方式反复查找值很昂贵(每次查找O(n)
复杂度)。创建新阵列将会非常昂贵,因为必须分配内存并且每次都要复制数据。
如果我了解您尝试做的事情,您可以尝试以下方法来获取新列。
首先使用groupby
按{' session'中的值对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)