Pandas性能:loc使用排序数据

时间:2018-05-22 14:53:53

标签: python performance pandas dataframe optimization

假设我们有一个100.000行和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的列表中,并创建一个路径变量来保存此访问者访问过的所有网址。

visitors = sortedData.visitorId.unique()
    visitors = visitors.tolist()
    paths = []
    visitor_length = len(visitors)

现在我所做的是为每个访问者进入一个循环,以便查找并存储每个访问者的遍历路径,他们的时间戳和ID,并将其用作辅助算法(不相关)中的输入。 我有两种方法可以做到这一点:

A:

for visitor in visitors:
    dataResult = sortedData.loc[sortedData['visitorId'] == visitor]
    timestamps = dataResult.timestamp.tolist()
    path = dataResult.pageUrl.tolist()

    paths.append((visitor, timestamps, path))
    sortedData = sortedData.iloc[len(dataResult):]

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

visitor列表中的每个唯一visitors重复此过程。

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

方式B使用数据始终排序的逻辑,因为visitors中的访问者1将始终是sortedData中的第一个访问者,访问者2中的第二个访客等等。所以我可以使用大熊猫value_counts()功能可以计算当前访问者的x次出现次数,只需使用x从第一行head(x)行中提取数据,因为它们始终匹配。这样,它不必每次都迭代并搜索整个数据帧。然后和以前一样,我从数据框中删除这些行,并为下一个visitor重复循环。

B:

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:]

令我惊讶的是,与来自A的10.89相比,它的运行速度几乎是6.31秒的两倍。

定时locvalue_counts()看起来后者更快,但是当在循环中使用时则相反。

考虑到B,我们知道访问者的位置,我们只需要遍历数据帧的前x行,而在A中我们每次都必须搜索整个数据帧,是什么导致了这种性能差异?

在之前的优化过程中,删除已经遍历的行,加速比较大,每次数据帧大小减半时加倍,而不是整数。这让我怀疑它每次都以A方式遍历整个数据帧,除非我遗漏了什么?

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

1 个答案:

答案 0 :(得分:1)

创建自己的访问者列表,迭代这些访问者并反复搜索数据框架并不理想。

如果我能正确理解您的问题,请查看可以在您的情况下使用的groupby

要使代码与您现有的代码类似,您可以这样开始:

grouped = sortedData.groupby('visitorId')

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