部分保留价值并有条件地替换观察值
Partially retaining value and conditionally replacing observation's value
数据集如下所示:
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
和 return 一个新的 Session_id
。 (例如第 3 次观察:Session_id
仍然是 A
,第 4 次观察改为 B
)。如果服务器改变了方式(即1
---->2
----->1
---->1
),它将return A
-----> A
----->B
---> C
,其中生成了B
由服务器 2
和 C
由第二个 1
生成
我的objective是判断记录中是否有子组。规则是:
Given the same IP, If the time difference between the current record and last record does not exceed 30 minutes,
then the record belongs to the same user.
我有一个指标变量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 编辑]
我正在考虑使用哈希对象来完成这项工作的可能性。我写了一些代码(显然它们不起作用并且可能会导致语法错误)。
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;
并且输出数据集只有两个观测值。谁能帮忙解释一下?
这是一个部分答案,因为我无法弄清楚您是如何构建 'Last_site'。在我看来你想要的是检查差异是否超过 30 mins/1800 秒,如果 'no',session_id 保持不变,如果 'yes',它采用新的session_id。我可能把你的问题简单化了,但结果似乎很接近:
data have;
input (Server IP Indicator Session_ID) (:.) 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;
数据集如下所示:
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
和 return 一个新的 Session_id
。 (例如第 3 次观察:Session_id
仍然是 A
,第 4 次观察改为 B
)。如果服务器改变了方式(即1
---->2
----->1
---->1
),它将return A
-----> A
----->B
---> C
,其中生成了B
由服务器 2
和 C
由第二个 1
我的objective是判断记录中是否有子组。规则是:
Given the same IP, If the time difference between the current record and last record does not exceed 30 minutes, then the record belongs to the same user.
我有一个指标变量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 编辑]
我正在考虑使用哈希对象来完成这项工作的可能性。我写了一些代码(显然它们不起作用并且可能会导致语法错误)。
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;
并且输出数据集只有两个观测值。谁能帮忙解释一下?
这是一个部分答案,因为我无法弄清楚您是如何构建 'Last_site'。在我看来你想要的是检查差异是否超过 30 mins/1800 秒,如果 'no',session_id 保持不变,如果 'yes',它采用新的session_id。我可能把你的问题简单化了,但结果似乎很接近:
data have;
input (Server IP Indicator Session_ID) (:.) 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;