【问题标题】:Partially retaining value and conditionally replacing observation's value部分保留价值并有条件地替换观察值
【发布时间】:2015-06-21 14:04:01
【问题描述】:

数据集如下所示:

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 -> 22 -> 1 )。在某些情况下,服务器在发生更改后立即更改(即1---->2----->1)。每当更改服务器时,服务器将记录最后一个Session_id,并在第二次浏览同一服务器时返回一个新的Session_id。 (例如第三次观察:Session_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;

问题是,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;

并且输出数据集只有两个观察值。谁能帮忙解释一下?

【问题讨论】:

    标签: hash sas retain


    【解决方案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;
    

    【讨论】:

      猜你喜欢
      • 2021-10-15
      • 1970-01-01
      • 1970-01-01
      • 2013-07-21
      • 2016-07-07
      • 1970-01-01
      • 2021-02-21
      • 1970-01-01
      • 2020-09-13
      相关资源
      最近更新 更多