SAS中的复杂数据重组问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SAS中的复杂数据重组问题相关的知识,希望对你有一定的参考价值。

我有一张卡片历史数据集如下。对于每个客户,他们可能在同一天申请了一张或多张卡。但是,由于各种原因,他们的卡被取代。发卡日期是发卡时。新卡ID是替换卡的ID。例如,对于客户A,他的卡在2017年2月1日首次发行,卡ID为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在5/2/217申请了两张卡。卡ID 1245,1248和1250属于同一组(Seq No 1),卡ID 1236,1249和1251属于同一组(Seq No 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,,
;
答案

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;

如果您真的需要客户中的Seq = 1..N,您将不得不进行额外的排序和合并。

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

另一答案

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

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

首先创建节点,“从/来自”卡数据中的数据。

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; 

以上是关于SAS中的复杂数据重组问题的主要内容,如果未能解决你的问题,请参考以下文章

JS复杂数据拆分重组

如何让SAS从第二行数据读取

使用文件中的代码作为 SAS 宏变量的内容

DEG聚类分析热图怎么看?

数据集 firstobs 中的错误

如何使用 .net 中的 SAS 密钥从 Azure Blob 读取数据