【问题标题】:SAS--How to identify the event occurred in three consecutive years?SAS--如何识别连续三年发生的事件?
【发布时间】:2020-02-25 22:15:47
【问题描述】:

我试图找出在一家公司连续三年中每年同一个月进行交易的交易者。一旦交易者符合标准,则应确定这三笔交易以及他在同一个月在该公司的所有后续交易。

假设我在下面有一个示例数据。

data have;
input ID  STOCK   trandate $12.;
datalines;
1    1   10/15/2009
1    1   01/01/2010
1    1   01/10/2011
1    1   01/15/2012
1    1   01/01/2013
1    2   01/30/2011
1    2   01/30/2012
1    2   01/30/2012
1    2   01/30/2013
1    2   01/30/2014
1    2   01/30/2015
2    1   01/20/2010
2    1   01/15/2011
2    1   01/16/2012
2    1   02/01/2013
2    2   02/01/2010
2    2   02/10/2011
2    2   02/10/2012
2    2   02/10/2013
2    2   02/10/2014
2    2   01/10/2015
;
run;

我需要什么:

ID Stock  trandate type
1    1   10/15/2009 0
1    1   01/01/2010 1
1    1   01/10/2011 1
1    1   01/15/2012 1
1    1   01/01/2013 1
1    2   01/30/2011 1
1    2   01/30/2012 1
1    2   01/30/2012 1
1    2   01/30/2013 1
1    2   01/30/2014 1
1    2   01/30/2015 1
2    1   01/20/2010 0
2    1   01/15/2011 0
2    1   01/16/2012 0
2    1   02/01/2013 0
2    2   02/01/2010 1
2    2   02/10/2011 1
2    2   02/10/2012 1
2    2   02/10/2013 1
2    2   02/10/2014 1
2    2   01/10/2015 0

我使用以下代码来实现这一点:

proc sort data=have;
by id stock trandate;
run;

data have;
set have;
month=month(trandate);
year=year(trandate);
run;

proc sort data=have;
by  id stock month year;
run;

data have;
set have;
by personid secid month year;

  rungroup + (first.month or not first.month and year - lag(year) > 1);

run;


data temp;
  do index = 1 by 1 until (last.rungroup);
    set have;
    by rungroup;

    * distinct number of years in rungroup;
    years_runlength = sum (years_runlength, first.rungroup or year ne lag(year));
  end;

  do index = 1 to index;
    set have;
    if years_runlength >=4 then output;
  end;
run;

以上代码用于识别过去连续三年有交易的交易者。由于我还需要这些交易者的后续交易。进一步应用以下代码。

proc sort data=temp;
by personid  secid   rungroup;
run;


data temp;
set temp;
by  rungroup;
if  first.rungroup then fyear=year;
run;

data temp(drop=fyear rename=(Locf=fyear));
 do until (last.personid);
   set  temp;
   by id stock;
   locf=coalesce(fyear,locf);
   output;
 end;
run;

data temp;
set temp;
by rungroup;
if first.rungroup then fmonth=month;
run;


data temp;
set temp;
gap=year-fyear;
run;


proc means data=temp;
var gap;
run;

data temp;
set temp;
if gap=3 then type2=1;
type1=1;
run;

以上代码用于标记连续三年后的第一笔交易。在这种情况下,当识别出的交易与原始数据集相结合时,可以识别出标记交易下的同月所有交易。从而达到“识别出这三笔交易以及他在该公司当月的所有后续交易”的目的。以下代码用于实现此目的。

proc sort data=have;
by id stock   rungroup;
run; 
proc sort data=temp;
by id stock   rungroup;
run; 



data combine;
merge have temp;
by id stock   rungroup;
run;


data combine;
set combine;
month=month(trandate);
run;



data combine1 (drop=fmonth rename=(Locf=fmonth));
 do until (last.personid );
   set  combine;
   by id stock;
   locf=coalesce(fmonth,locf);
   output;
 end;
run;


data combine2 (drop=type2 rename=(Locf=type2));
 do until (last.personid);
   set  combine1;
   by id stock;
   locf=coalesce(type2,locf);
   output;
 end;
run;

    data combine2;
    set combine2;
    if month^=fmonth then type2=.;
    run;

data combine2;
set combine2;
if type1=1 or type2=1 then type=1;
else type=0;
run;

我尝试了这些代码,结果看起来正确,但我不能 100% 确定。此外,如您所见,我的代码相对较长且复杂。那么有人可以给我一些关于代码的建议吗?

【问题讨论】:

  • ID=2 和 STOCK=1 的新标志不应该为真吗?月份 1 连续三年出现:2011、2012 和 2013。

标签: date sas


【解决方案1】:

这是一种蛮力的方式。对于这个例子,我只是在你的例子中将它限制在 2009 年到 2015 年,但你可以扩展模式以允许更多年。您可以使用宏逻辑来生成代码的壁纸方面。

首先生成一个可以按 YEAR 和 MONTH 索引的数组,并在它代表的月份有交易时用 1 填充变量。然后检查多年来同一月份的一系列值是否连续三个 1。您可以使用两个 DOW 循环来处理数据。第一个填充数组,第二个测试数组并设置新的标志变量。

data want ;
 do until(last.stock) ;
   set have ;
   by id stock;
   array months [1:12,2009:2015] 
     m1y2009-m1y2015 m2y2009-m2y2015 m3y2009-m3y2015 m4y2009-m4y2015
     m5y2009-m5y2015 m6y2009-m6y2015 m7y2009-m7y2015 m8y2009-m8y2015
     m9y2009-m9y2015 m10y2009-m10y2015 m11y2009-m11y2015 m12y2009-m12y2015
   ;
   months[month(trandate),year(trandate)]=1;
 end;
 do until(last.stock);
   set have;
   by id stock;
   select (month(trandate));
     when (1) flag=0 ne index(cats(of m1y:),'111');
     when (2) flag=0 ne index(cats(of m2y:),'111');
     when (3) flag=0 ne index(cats(of m3y:),'111');
     when (4) flag=0 ne index(cats(of m4y:),'111');
     when (5) flag=0 ne index(cats(of m5y:),'111');
     when (6) flag=0 ne index(cats(of m6y:),'111');
     when (7) flag=0 ne index(cats(of m7y:),'111');
     when (8) flag=0 ne index(cats(of m8y:),'111');
     when (9) flag=0 ne index(cats(of m9y:),'111');
     when (10) flag=0 ne index(cats(of m10y:),'111');
     when (11) flag=0 ne index(cats(of m11y:),'111');
     when (12) flag=0 ne index(cats(of m12y:),'111');
     otherwise ;
   end;
   output;
  end;
  drop m: ;
run;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-21
    • 1970-01-01
    • 1970-01-01
    • 2022-11-15
    • 1970-01-01
    相关资源
    最近更新 更多