我如何优化这个在点击流中查找会话持续时间的循环?
How can I optimize this for loop that finds session duration in clickstreams?
我是 Python 数据科学的初学者,我正在做点击流分析。我的文件太大——大约 3300 万行。我是 运行 我制作的用于查找会话持续时间的脚本。我正在打印 i 以查找操作进度。然而,将近 12 个小时过去了,我只达到了 400 000。它有将近 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 列中同时更新最终减法。
adi = "H:/excelfiles/clicks3.csv"
k = pandas.read_csv(adi)
k.columns=['Sid','Tstamp','Itemid']
#Dropping Redundant Columns
k.drop(k.columns[2],axis=1,inplace=True)
#Stores max timestamp in amax
idx=k.groupby(['Sid'])['Tstamp'].transform(max) == k['Tstamp']
amax=k[idx].set_index('Sid')
#Stores min timestamp in amin
idy=k.groupby(['Sid'])['Tstamp'].transform(min) == k['Tstamp']
amin=k[idy].set_index('Sid')
i=0
for temp1,temp2,temp3 in zip(amax['Tstamp'],amax.index,amin['Tstamp']):
sv1= datetime.datetime.strptime(temp1, "%Y-%m-%dT%H:%M:%S.%fZ")
sv2= datetime.datetime.strptime(temp3, "%Y-%m-%dT%H:%M:%S.%fZ")
if(i%1000==0):
print i
d1=time.mktime(sv1.timetuple()) + (sv1.microsecond / 1000000.0)
d2=time.mktime(sv2.timetuple()) + (sv2.microsecond / 1000000.0)
amax.loc[temp2,'duration']= (d1-d2)/60
i=i+1
#amax stores the final session duration
amax=amax.reset_index()
如何优化此代码。
编辑 1:删除了微秒部分。
好的,如果你可以忽略微秒或毫秒部分,你可以试试我的模块 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 for 循环。
像这样
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
这是使用标准 pandas 方法的一种非常简单的方法。您真正需要做的就是将 'Tstamp' 转换为 pandas 日期时间,然后取最大值和最小值的差值。由于它是日期时间,因此差异自动是时间增量。
>>> 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]
我是 Python 数据科学的初学者,我正在做点击流分析。我的文件太大——大约 3300 万行。我是 运行 我制作的用于查找会话持续时间的脚本。我正在打印 i 以查找操作进度。然而,将近 12 个小时过去了,我只达到了 400 000。它有将近 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 列中同时更新最终减法。
adi = "H:/excelfiles/clicks3.csv"
k = pandas.read_csv(adi)
k.columns=['Sid','Tstamp','Itemid']
#Dropping Redundant Columns
k.drop(k.columns[2],axis=1,inplace=True)
#Stores max timestamp in amax
idx=k.groupby(['Sid'])['Tstamp'].transform(max) == k['Tstamp']
amax=k[idx].set_index('Sid')
#Stores min timestamp in amin
idy=k.groupby(['Sid'])['Tstamp'].transform(min) == k['Tstamp']
amin=k[idy].set_index('Sid')
i=0
for temp1,temp2,temp3 in zip(amax['Tstamp'],amax.index,amin['Tstamp']):
sv1= datetime.datetime.strptime(temp1, "%Y-%m-%dT%H:%M:%S.%fZ")
sv2= datetime.datetime.strptime(temp3, "%Y-%m-%dT%H:%M:%S.%fZ")
if(i%1000==0):
print i
d1=time.mktime(sv1.timetuple()) + (sv1.microsecond / 1000000.0)
d2=time.mktime(sv2.timetuple()) + (sv2.microsecond / 1000000.0)
amax.loc[temp2,'duration']= (d1-d2)/60
i=i+1
#amax stores the final session duration
amax=amax.reset_index()
如何优化此代码。
编辑 1:删除了微秒部分。
好的,如果你可以忽略微秒或毫秒部分,你可以试试我的模块 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 for 循环。
像这样
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
这是使用标准 pandas 方法的一种非常简单的方法。您真正需要做的就是将 'Tstamp' 转换为 pandas 日期时间,然后取最大值和最小值的差值。由于它是日期时间,因此差异自动是时间增量。
>>> 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]