【问题标题】:Complex data restructure issue in SASSAS中的复杂数据重组问题
【发布时间】:2017-12-18 12:39:49
【问题描述】:

我有一个卡片历史数据集,如下所示。对于每位客户,他们可能在同一天申请了一张或多张卡。但是,由于各种原因,他们的卡被更换了。发卡日期是发卡的日期。新卡 ID 是替换卡的 ID。比如客户A,他的卡是2017年2月1日第一次发卡,卡号是1234,3天后卡丢了,2017年5月2日又发了一张新卡(1235)。

Customer ID First Issue Date    Card Issue Date Card ID New Card ID
A   2/1/2017    2/1/2017    1234    1235
A   2/1/2017    5/2/2017    1235     
B   5/2/2017    5/2/2017    1245    1248
B   5/2/2017    5/2/2017    1236    1249
B   5/2/2017    10/3/2017   1248    1250
B   5/2/2017    5/3/2017    1249    1251
B   5/2/2017    10/4/2017   1250     
B   5/2/2017    5/4/2017    1251    

 

我想要的是将原始卡和所有替换卡组合在一起。例如,客户 B 在 217 年 5 月 2 日申请了两张卡。卡 ID 1245、1248 和 1250 属于同一组(序列号 1),卡 ID 1236、1249 和 1251 属于同一组(序列号 2)。

Customer ID Open Date   Card Issue Date Card ID Seq No
A   2/1/2017    2/1/2017    1234    1
A   2/1/2017    5/2/2017    1235    1
B   5/2/2017    5/2/2017    1245    1
B   5/2/2017    10/3/2017   1248    1
B   5/2/2017    10/4/2017   1250    1
B   5/2/2017    5/2/2017    1236    2
B   5/2/2017    5/3/2017    1249    2
B   5/2/2017    5/4/2017    1251    2

请帮我完成这个数据转换。

这是输入文件的数据步骤

data test;
infile datalines dsd truncover ;
input Customer:$1.
First_Issue_Date: ddmmyy10.
Card_Issue_Date: ddmmyy10.
Card_ID: $4.
New_Card_ID: $4. ;
format First_Issue_Date ddmmyy10. Card_Issue_Date ddmmyy10.;
datalines;
A,02/01/2017,02/01/2017,1234,1235,
A,02/01/2017,05/02/2017,1235,,
B,05/02/2017,05/02/2017,1245,1248,
B,05/02/2017,05/02/2017,1236,1249,
B,05/02/2017,10/03/2017,1248,1250,
B,05/02/2017,05/03/2017,1249,1251,
B,05/02/2017,10/04/2017,1250,,
B,05/02/2017,05/04/2017,1251,,
;

【问题讨论】:

  • 如果您无法访问 proc optnet,您也许可以调整我发布的答案 here

标签: sas


【解决方案1】:

DATA Step 哈希对象对于遍历身份跟踪数据中的路径非常有效。假设每个 Card_ID 对所有客户都是唯一的,并且每个 New_Card_ID 值在数据集中都有一个对应的 Card_ID 值,那么这段代码将在无数的补发中找到唯一的路径 ID。

data paths(keep=card_id path_id);
  if 0 then set have; * prep pdv;

  call missing (Path_ID);

  * for tracking the tip of the card_id trail;
  DECLARE HASH currentCard(hashexp: 9);
  currentCard.defineKey ('Card_ID');
  currentCard.defineData ('Card_ID', 'Path_ID');
  currentCard.defineDone();

  * for tracking everything up to the tip (segment);
  DECLARE HASH replacedCard(hashexp:10);
  replacedCard.defineKey ('New_Card_ID');     
  replacedCard.defineData('Card_ID');
  replacedCard.defineDone();

  * fill the two hashes;
  do until (lastrow);
    set have (keep=Card_ID New_Card_ID) end=lastrow;

    if missing(New_Card_ID) then 
      Path_ID + 1;

    if missing(New_Card_ID)
      then currentCard.add();
      else replacedCard.add(); 
  end;

  * for each tip of a path output the tip and all its segments;
  declare hiter tipIter('currentCard');
  do while (tipIter.next() = 0);
    output; * tip;

    do while (replacedCard.find(key:Card_ID) = 0);
      output; * segment;
    end;
  end;

  stop;
run;

如果您在 Customer 中确实需要 Seq = 1..N,则必须进行额外的排序和合并。

我的 NESUG 2009 论文 "Using HASH to find a sum over a transactional path" 对关联交易进行了类似的讨论。

【讨论】:

    【解决方案2】:

    您正在寻找的是连通分量分析。如果你有,PROC OPTNET 可以给你你想要的。

    很遗憾,它不支持BY 语句,因此您必须在使用它对卡片进行分组后生成序列号。

    首先从您的卡数据中创建节点,“to/from”数据。

    data nodes;
    set test;
    node = put(_n_,best12.);
    from = card_id;
    to = new_card_id;
    if to = . then to=from;
    run;
    

    然后运行分析。

    proc optnet data_links=nodes out_nodes=nodes_out;
    concomp;
    run;
    

    这会生成一张卡片列表及其组(变量concomp)。

    将该组加入到原始数据并对其进行排序。

    proc sql noprint;
    create table want as
    select a.customer,
           a.First_Issue_Date,
           a.Card_Issue_Date,
           a.Card_ID,
           b.concomp
        from test as a
          left join
             nodes_out as b
        on a.card_id = b.node
        order by customer, concomp, Card_Issue_Date;
    quit;
    

    现在这些组只是按 1、2、...、N 排序。您可以使用数据步骤获取该信息并创建 seq_no

    data want(drop=concomp);
    set want;
    by customer concomp;
    retain seq_no ;
    
    if first.customer then
        seq_no = 0;
    if first.concomp then
        seq_no = seq_no + 1;
    run; 
    

    【讨论】:

    • 感谢您的解决方案。但是,我没有 OR 包。
    猜你喜欢
    • 2017-04-18
    • 2015-01-05
    • 1970-01-01
    • 1970-01-01
    • 2017-11-29
    • 1970-01-01
    • 1970-01-01
    • 2016-06-18
    • 2011-09-21
    相关资源
    最近更新 更多