数据集如下所示:
Server IP Indicator Session_ID Time
2 1.20.54.221 A 00:00:01
2 1.20.54.221 A 00:01:00
1 1.20.54.221 Site A 00:02:00
1 1.20.54.221 B 00:05:00
2 1.20.54.221 Site B 00:08:00
2 1.20.54.221 C 00:10:00
2 1.20.54.221 C 00:15:00
1 1.20.54.221 F 01:00:00
1 1.20.54.221 F 01:05:00
2 1.20.54.221 Site F 01:08:00
从日志文件中读取上述数据集。服务器更改时Session_id
会发生变化(例如1
- > 2
或2
- > 1
)。在某些情况下,服务器会在发生更改后立即更改(即1
----> 2
-----> 1
)。每当更改服务器时,服务器将记录最后Session_id
并在第二次浏览同一服务器时返回新的Session_id
。 (例如第3次观察:Session_id
仍为A
,并在第4次观察时更改为B
。如果服务器发生了变化(即1
----> 2
-----> 1
----> 1
),它将返回A
-----> A
- - - - > B
---> C
,其中B
由服务器2
生成,C
由第二个1
生成
我的目标是确定记录中是否有子组。规则是:
给定相同的IP,如果当前记录与最后一条记录之间的时差不超过30分钟, 然后该记录属于同一用户。
我有一个指标变量site
来确定网站是否已更改。它根据服务器的更改是否发生以及时间差是否小于30分钟进行标记。
所需数据集
Server IP Indicator Session_ID Time Difference Last_site
2 1.20.54.221 A 00:00:01 . .
2 1.20.54.221 A 00:01:00 59s .
1 1.20.54.221 Site A 00:02:00 1 Min .
1 1.20.54.221 A 00:05:00 3 Min Site
2 1.20.54.221 Site A 00:08:00 3 Min Site
2 1.20.54.221 A 00:10:00 2 Min Site
2 1.20.54.221 A 00:15:00 5 Min Site
1 1.20.54.221 F 01:00:00 45min .
1 1.20.54.221 F 01:05:00 5 Min .
2 1.20.54.221 Site F 01:08:00 3 Min .
我的实施:
data log_file;
set log;
retain _Session_id Last_site;,
* Assign value to retain ;
if indicator = "Site" then _Session_id = Session_id;
* if last_site = Site, its value has to be changed;
last_site=lag(site);
* Record that should be in another group ;
if difference >30 then Last_Site = "";
* Replace;
if last_site not eq "" then session_id = _session_id
run;
问题是,retained variable
会在第五次观察时从A
更改为B
,而我希望它保持值A
直到我发现时差大于30
分钟的记录。 (这个过程将循环超过数十万个IP,因此效率也受到关注。)
有没有办法优雅地处理问题? 先感谢您。
[编辑于22/6]
我在考虑使用Hash Object来完成这项工作的可能性。我写了一些代码(显然它们不起作用,可能会导致语法错误)。
data test11a;
length mark $ 12 ip $ 32 Session_id $ 200 agent last_agent $ 200; <== the system said there is error with the type of variable and therefore I add this
Declare hash hid;
hid = _new_ hash( ordered : ' ascending');
hid.definekey('ip');
hid.definedata('Session_id');
hid.definedone();
call missing ( ip, Session_id);
do while ( not done);
set test11 end=done; <==== I have the original data-set called test11
by ip notsorted ; <==== hash object by group;
if not first.ip or not last.ip then do;
if mark = "Site" then rc= hid.add();
*if mark = "Next_Group" then hid.remove(key : ip); <=== Error
end;
if mark not eq "Site" or "Next_Group" then do;
rc=hid.find(); <==== Find matching iP and if matching ( rc=0)
* use variable _ session_id to test;
if rc = 0 then _session_id = Session_id;
end;
end;
run;
输出数据集只有两个观察结果。有人可以帮忙解释一下吗?
答案 0 :(得分:1)
这是一个部分答案,因为我无法弄清楚你如何构建'Last_site'。在我看来你想要的是检查差异是否超过30分钟/ 1800秒,如果“否”,则session_id保持不变,如果“是”,则采用新的session_id。我可能会过度简化您的问题,但结果似乎很接近:
data have;
input (Server IP Indicator Session_ID) (:$20.) Time :time8.;
format time time8.;
cards;
2 1.20.54.221 . A 00:00:01
2 1.20.54.221 . A 00:01:00
1 1.20.54.221 Site A 00:02:00
1 1.20.54.221 . B 00:05:00
2 1.20.54.221 Site B 00:08:00
2 1.20.54.221 . C 00:10:00
2 1.20.54.221 . C 00:15:00
1 1.20.54.221 . F 01:00:00
1 1.20.54.221 . F 01:05:00
2 1.20.54.221 Site F 01:08:00
;
run;
data want;
set have;
by ip notsorted;
retain _session ' ';
if first.ip then
_session=session_id;
difference=dif(time);
if difference > 1800 then
_session=session_id;
drop session_id;
rename _session=session_id;
run;