sas:根据日期统计行数

sas:根据日期统计行数,sas,Sas,我正在处理犯罪数据。现在,我有下表犯罪。每行包含一个特定的犯罪(例如袭击):犯罪日期(日期)和罪犯的个人ID(个人) 我感兴趣的是,在同一个人犯下第一次罪行后的1年内,每个人是否犯下(复发=1)或没有犯下(复发=0)另一次罪行。另一个条件是第一次犯罪必须在特定年份内发生(此处为2017年) 因此,结果应如下所示: date person relapse ------------------------------ 02JAN2017 1 1

我正在处理犯罪数据。现在,我有下表
犯罪
。每行包含一个特定的犯罪(例如袭击):犯罪日期(
日期
)和罪犯的个人ID(
个人


我感兴趣的是,在同一个人犯下第一次罪行后的1年内,每个人是否犯下(复发=1)或没有犯下(复发=0)另一次罪行。另一个条件是第一次犯罪必须在特定年份内发生(此处为2017年)

因此,结果应如下所示:

date       person     relapse
------------------------------
02JAN2017       1           1  
03FEB2017       1           1
04JAN2018       1           1
27NOV2017       2           0 
28NOV2018       2           0 
01MAY2017       3           1
24FEB2018       3           1
10OCT2017       4           0
谁能告诉我如何在SAS中实现这一点?
很明显,实际数据要大得多,所以我无法手动操作。

一种方法是使用数据逐步分组处理

BY
语句设置二进制变量
first.
last.
标记组中的第一行和组中的最后一行

您似乎正在为整个组分配computed Recurse标志,这种计算可以通过SAS编码人员称之为DOW循环的方式完成——循环中包含
SET
语句的循环,以及将计算分配给组中每一行的后续循环

INTCK
函数可以计算两个日期之间的年数

例如:

data want(keep=person date relapse);
  * DOW loop computes assertion that relapse occurred;

  relapse = 0;
  do _n_ = 1 by 1 until (last.person);

    set crimes;          * <-------------- CRIMES;
    by person date;

    * check if persons first crime was in 2017;
    if _n_ = 1 and year(date) = 2017 then _first = date;

    * check if persons second crime was within 1 year of first;
    if _n_ = 2 and _first then relapse = intck('year', _first, date, 'C') < 1;
  end;

  * at this point the relapse flag has been computed, and its value
  * will be repeated for each row output;

  * serial loop over same number of rows in the group, but 
  * read in through a second SET statement;

  do _n_ = 1 to _n_;
    set crimes;              * <-------------- CRIMES;
    output;
  end;
run;
所需数据(keep=person-date-recurse);
*DOW loop计算复发发生的断言;
复发率=0;
1乘1直到(最后一人);

设定罪行;* 我是最近才开始使用sas的——我并没有试图在这里创建完美的代码

我会先按id/人和日期对数据进行排序(日期应该是数字),然后使用retain语句检查第一次犯罪的日期。它不是完美的,但如果你的数据是好的(没有遗漏日期),它会工作,并且很容易遵循imho

只有在2017年出现第一次犯罪记录和行为的情况下,这才有效。如果您在2016年发生了犯罪,并且希望检查2017年是否发生了“犯罪”,然后检查复发,那么此代码将不起作用-但我认为您的问题下面的评论中包含了这一点

data test;
input tmp_year $ 1-9 person;  
datalines;
02JAN2017       1        
03FEB2017       1      
04JAN2018       1    
27NOV2017       2      
28NOV2018       2    
01MAY2017       3
24FEB2018       3
10OCT2017       4
;
run;

data test2;
    set test;
    crime_date = input(tmp_year, date9.);
    act_year = year(crime_date);
run;

proc sort data=test2;
   by person crime_date ;
run;

data want;
    set test2;
    by person crime_date;
    retain date_of_crime;
    if first.person and act_year = 2017 then date_of_crime = crime_date;
    else if first.person then call missing(date_of_crime);
    if intck('YEAR', date_of_crime, crime_date) =< 1 and not first.person 
    then relapse = 1;
    else relapse = 0;
run;
数据测试;
输入tmp_年$1-9人;
数据线;
2017年1月2日1
2017年2月3日1
2018年1月4日1
2017年11月27日2
2018年11月28日2
2017年5月1日3
2018年2月24日3
2017年10月10日4
;
跑
数据测试2;
集合测试;
犯罪日期=输入(tmp年,日期9);
行为年=年(犯罪日期);
跑
proc sort data=test2;
按个人犯罪日期;
跑
数据需求;
设置test2;
按个人犯罪日期;
保留犯罪日期;
如果第一人称和行为年=2017年,则犯罪日期=犯罪日期;
否则,如果第一个人打电话失踪(犯罪日期);
如果intck(‘年份’、犯罪日期、犯罪日期)=<1且不是第一人称
然后复发=1;
else复发率=0;
跑

上述代码标记了2017年犯罪行为一年后的犯罪行为。然后,您可以使用proc sql语句检索唯一的人员,并将他们与您拥有的任何数据集连接起来

如果有人在2017年1月、2018年2月和2018年3月犯罪怎么办?(请在问题中填写您的示例)那么,由于2018年2月和2018年3月发生的犯罪在2017年1月之后超过一年,因此不会再次发生。但是,如果这段时间是5年而不是1年,那么他们将被视为复发。如果有人在2016年1月、2017年2月和2017年3月犯罪怎么办?另一个条件是第一次犯罪必须在特定的一年内发生(这里是2017年)。
data test;
input tmp_year $ 1-9 person;  
datalines;
02JAN2017       1        
03FEB2017       1      
04JAN2018       1    
27NOV2017       2      
28NOV2018       2    
01MAY2017       3
24FEB2018       3
10OCT2017       4
;
run;

data test2;
    set test;
    crime_date = input(tmp_year, date9.);
    act_year = year(crime_date);
run;

proc sort data=test2;
   by person crime_date ;
run;

data want;
    set test2;
    by person crime_date;
    retain date_of_crime;
    if first.person and act_year = 2017 then date_of_crime = crime_date;
    else if first.person then call missing(date_of_crime);
    if intck('YEAR', date_of_crime, crime_date) =< 1 and not first.person 
    then relapse = 1;
    else relapse = 0;
run;