Python 熊猫性能:loc与使用排序数据的前x行中的.head(x)的对比

Python 熊猫性能:loc与使用排序数据的前x行中的.head(x)的对比,python,performance,pandas,dataframe,optimization,Python,Performance,Pandas,Dataframe,Optimization,假设我们有一个包含100000行和3列的数据框架,其结构如下: | visitorId | timestamp | url | 1 | 1 | 11 | A | 2 | 1 | 12 | B | 3 | 2 | 21 | A | 4 | 3 | 31 | A | 5 | 3 | 32 | C | . . n | z

假设我们有一个包含100000行和3列的数据框架,其结构如下:

  | visitorId | timestamp | url |
1 | 1         | 11        |  A  |
2 | 1         | 12        |  B  |
3 | 2         | 21        |  A  |
4 | 3         | 31        |  A  |
5 | 3         | 32        |  C  |
.
.
n | z         | Z1        |  A  |
此数据帧始终被排序,并存储在名为
sortedData
的变量中。首先,我们将所有唯一的访问者ID提取到一个名为
visitors
的列表中,并创建一个path变量来保存该访问者访问过的所有URL

visitors = sortedData.visitorId.unique()
    visitors = visitors.tolist()
    paths = []
    visitor_length = len(visitors)
现在,我所做的是为每个访问者进入一个循环,以查找和存储每个访问者的遍历路径、时间戳和ID,并将其作为辅助算法的输入(不相关)。 我用了两种方法来做到这一点:

A:

这使用内置的pandas
loc
函数查找具有匹配的
visitorId
的行,并将时间戳和路径提取到列表中,最后将它们附加在一起。然后,它继续删除前x行(等于查询结果的长度,也称为匹配数),以便在以后进行类似匹配时不会遍历它们

对于
访问者
列表中的每个唯一的
访问者
,重复该过程

通过计时,我发现大约需要6.31秒才能完成。在我的例子中,这是一个11.7MB的文件,10万行。在1.2GB的文件上,此文件可扩展到14小时。因此,我尝试了方法B,希望加速

方式B使用数据总是被排序的逻辑,例如
visitors
中的访问者1总是
sortedData
中的第一个访问者,访问者2总是第二个访问者等。因此我可以使用pandas
value\u counts()
函数来计算当前访问者的出现次数
x
,使用
head(x)
从第一行
x
提取数据,因为它们总是匹配的。这样,它就不必每次都迭代和搜索整个数据帧。然后像以前一样,我从数据帧中删除这些行,并为下一个
访问者重复循环

B:

令我惊讶的是,这使得它的运行速度几乎是a的两倍,达到
10.89
秒,而a的
6.31

loc
value\u counts()进行计时后者似乎更快,但在循环中使用时,情况正好相反

考虑到在B中,我们知道访问者的位置,我们只需要迭代数据帧的前x行,在A中,我们每次都要搜索整个数据帧,是什么导致性能上的差异

在我之前做的优化中,删除已经遍历的行时,速度提升相当可观,每次数据帧大小减半时,速度都会翻倍,而不是保留整个数据帧。这让我怀疑它每次都以某种方式遍历整个数据帧,除非我遗漏了什么


我使用的是运行在PyCharm 2018上的MacBook Pro 2014,Python 3.6.4(Anaconda)。

创建自己的访客列表,反复浏览并搜索数据框并不理想

如果我正确理解你的问题,请看一看,它可以用于你的情况

要获得与现在类似的代码,可以从以下方式开始:

grouped = sortedData.groupby('visitorId')

for visitorId, group in grouped:
    print(vistorId)
    # your code here
    custom_url_algorithm(group)

对确切地说,您每次都在这里迭代整个数据集:
sortedData['visitorId']==visitor
这就解决了它!作为参考,1.2GB文件从14小时缩短到7分钟。我使用例如
time=grouped.get\u group(visitorId.timestamp.tolist()
for visitor in visitors:
    x = sortedData.visitorId.value_counts()[visitor]
    timestamps = sortedData.timestamp.head(x).tolist()
    path = sortedData.pageUrl.head(x).tolist()

    paths.append((visitor, timestamps, path))
    sortedData = sortedData.iloc[x:]
grouped = sortedData.groupby('visitorId')

for visitorId, group in grouped:
    print(vistorId)
    # your code here
    custom_url_algorithm(group)