Hash 部分保留价值并有条件地替换观察';s值

Hash 部分保留价值并有条件地替换观察';s值,hash,sas,retain,Hash,Sas,Retain,数据集如下所示: 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

数据集如下所示:

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
上述数据集是从日志文件中读取的<代码>会话id将在服务器更改时更改(即
1
->
2
2
->
1
)。有些情况下,服务器会在发生更改后立即更改(即
1
-->
2
-->
1
)。无论何时更改服务器,服务器都会记录最后一次
会话id
,并在第二次浏览同一服务器时返回新的
会话id
。(例如,第三次观察:
Session\u id
仍然
A
,第四次观察改为
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;
我的实现:

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;
问题是,
保留变量
将在第五次观察时从
A
变为
B
,而我希望它保持值
A
,直到我找到一个时差大于
30
min的记录。(该过程将循环数十万个IP,因此效率也受到关注。)

有没有可能优雅地处理这个问题? 先谢谢你

[于6月22日编辑]

我正在考虑使用Hash对象来完成这项工作的可能性。我写了一些代码(显然它们不起作用,可能会导致语法错误)

数据测试11a;

长度标记$12 ip$32会话id$200代理上次代理$200 这是一个部分答案,因为我不知道你是如何构建“最后一个站点”的。在我看来,您想要的是检查差异是否超过30分钟/1800秒,如果“否”,会话id保持不变,如果“是”,则采用新的会话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;