如何针对在点击流中查找会话持续时间的循环优化此操作?

时间:2016-03-14 01:29:25

标签: python performance pandas data-science

我是Python数据科学的初学者,我正在进行点击流分析。我的文件太大 - 大约3300万行。我正在运行这个脚本来查找会话持续时间。我正在打印i以查找操作的进度。然而接近12个小时已经过去了,我只达到了40万小时。它已接近900万次。使用此速度将需要近270小时(11天)。我需要优化它以减少时间。

这是数据集:

             Sid                    Tstamp     Itemid
0              1  2014-04-07T10:54:09.868Z  214536500
1              1  2014-04-07T10:54:46.998Z  214536506
2              1  2014-04-07T10:57:00.306Z  214577561
3              2  2014-04-07T13:56:37.614Z  214662742
4              2  2014-04-07T13:57:19.373Z  214662742
5              2  2014-04-07T13:58:37.446Z  214825110
6              2  2014-04-07T13:59:50.710Z  214757390
7              2  2014-04-07T14:00:38.247Z  214757407
8              2  2014-04-07T14:02:36.889Z  214551617

这是我的代码。我认为for循环正在减慢操作。对于会话持续时间,我首先在每个会话中查找最大和最小时间戳。然后在for循环中我将它们转换为seconds.microseconds,然后在Tstamp列中同时更新最终减法。

INNER JOIN

可以采取哪些措施来优化此代码。

编辑1:删除了微秒部分。

2 个答案:

答案 0 :(得分:2)

这是使用标准pandas方法的一种非常简单的方法。你真正需要做的就是将'Tstamp'转换为pandas datetime,然后取最大值和最小值的差值。由于它是一个日期时间,因此差异自动为时间差值。

>>> import pandas as pd

>>> k['Tstamp'] = pd.to_datetime( k['Tstamp'] ) 

>>> duration = ( k.groupby('Sid')['Tstamp'].max() 
               - k.groupby('Sid')['Tstamp'].min() )

Sid
1   00:02:50.438000
2   00:05:59.275000
Name: Tstamp, dtype: timedelta64[ns]

答案 1 :(得分:0)

好的,如果您可以忽略微秒或毫秒部分,您可以尝试我的名为 mktime 的模块。

安装

pip install mktime

用法

import mktime
mktime.mktime("2014-04-07T10:54:09.868Z")
# 1396868049

性能测试

% cat test.py
from mktime import mktime
import datetime
import time

temp1 = "2014-04-07T10:54:09.868Z"

def test1():
    sv1 = datetime.datetime.strptime(temp1, "%Y-%m-%dT%H:%M:%S.%fZ")
    d1=time.mktime(sv1.timetuple()) + (sv1.microsecond / 1000000.0)
    #print d1

def test2():
    d1 = mktime(temp1)
    #print d1

结果(我的机器 100 倍)

% python -m timeit -s 'import test' 'test.test1()'
10000 loops, best of 3: 20 usec per loop
% python -m timeit -s 'import test' 'test.test2()'
1000000 loops, best of 3: 0.199 usec per loop

如果你有数百万,你还可以使用itertools.izip循环,但没有在内存中分配整个列表。

像这样的东西

from mktime import mktime
from itertools import izip

i = 0
for temp1,temp2,temp3 in izip(amax['Tstamp'],amax.index,amin['Tstamp']):
    if(i%1000==0):    
        print i
    amax.loc[temp2,'duration']= (mktime(temp1) - mktime(temp3)) / 60.0
    i=i+1