SAS中文论坛

 找回密码
 立即注册

扫一扫,访问微社区

楼主: shiyiming
打印 上一主题 下一主题

SAS程序员测试(二)

[复制链接]

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
11#
 楼主| 发表于 2004-6-4 22:43:25 | 只看该作者

回复

proc sort;by id vol date;run;

data t;set tem;
by id vol;
if first.vol then do;
sdate=date;output;
end;
if last.vol & not first.vol then do;
edate=date;output;
end;
run;

data t1;set t;if sdate>0;
keep id vol sdate ;
run;
data t2;set t2;if edate>0;
keep id vol edate;
run;

data m;merge t1 t2;by id vol;
if edate=. then edate=sdate;
format sdate edate yymmdd10.;
run;
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
12#
 楼主| 发表于 2004-6-5 18:14:02 | 只看该作者

My Solution

Wow, it is good to see many SAS programmers are trying this one out, I hope you have enjoyed it.  

There are definitely many ways to do it,  the key is to have a clear logic to handle it.  I wrote the following program to do this, and any comment is welcome.

I will try to read some of your programs and give you some of my inputs.
                                                                                                                                                                                                                                       
data result(keep=id1 from to vol1);                                                                                                     
retain id1 from to vol1;                                                                                                               
format from to yymmdd10.;                                                                                                               
set tem;                                                                                                                                
by id date;                                                                                                                             
                                                                                                                                       
if first.id then do;                                                                                                                    
  id1=id; from=date; to=date; vol1=vol;                                                                                                
end;                                                                                                                                    
else do;                                                                                                                                
  if (vol ne vol1) or (date ne to+1) then do;                                                                                          
     output;                                                                                                                           
     from=date; to=date; vol1=vol;                                                                                                      
  end;                                                                                                                                 
  else do;                                                                                                                              
     to=date;                                                                                                                           
  end;                                                                                                                                 
end;                                                                                                                                    
                                                                                                                                       
if last.id then do;                                                                                                                     
  to=date;                                                                                                                              
  output;                                                                                                                              
end;                                                                                                                                    
                                                                                                                                       
run;
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
13#
 楼主| 发表于 2004-6-5 19:22:10 | 只看该作者

To Willon

I have gone through Willon's program, it is pretty good and the logic is clear.  But, there is a minor problem.

If you delete the throd record, '1 20020102 10', the program will no longer work.  The reason is that you did not consider the time gap when a subject stay on same vol.  

Besides, the call of the macro variable SDATE may not be necessary, since you have already retained it and its value changes over iterations.

Just my 2 cents.
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
14#
 楼主| 发表于 2004-6-6 00:17:31 | 只看该作者

....

Give sincere thanks to XIC for pointing out my mistakes caused by my carelessness.

......
if first.id then call symput('sdate',date);
else do;
   [color=red:6567f]if lag_vol^=vol then do;[/color:6567f]
......

the RED line must be replaced with
   [color=red:6567f]if lag_vol^=vol or date^=lag_date+1 then do;[/color:6567f]

The aim of "RETURN" is only to change the order of variables in output table,Originally,I thinked less of it.So thank you again for your suggestion.
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
15#
 楼主| 发表于 2004-6-6 01:29:27 | 只看该作者

To QSMY

I have read the program of QSMY, but not into the detail.

First,  the program will not run;  I assume that the line
data t2; set t2;
should be data t2; set t;

Second, the logic of this program has a problem.  If a subject has same volumn on different dates and the dates are not in a continuous episode, just as it happened in the data, the program will fail.

Just re-run the program and compare your output with the answer given by Willon, you can see that the output is not  correct.
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
16#
 楼主| 发表于 2004-6-6 02:06:11 | 只看该作者

To GENECHINA

I have read both of your program, and they are impressive because of the simplicity.  But, I think you did not consider a key condistion.  As in previous postings, if you delete the third data line, '1 20020102 10', you will see that the program will not generate the correct answer.  

There is another comment which is also very important to all SAS programmers.  As we know, the order of the records and the order of variables in a database or a data set does not make too much sense.  Changing the order does not change the nature of the data.  If a program depends upon the order, you had better to add BY statement for each data step.  LAG and DIF functions are order dependent, you have to keep them in mind.  Besides, when you do MERGE, you had better have a BY statement.  MERGE without BY is very dangerous except you know exactly what are you doing.

As matter of fact, in my opinion, it is something SAS need to be modified in future.  As we know, when you use FIRST.X or LAST.X, SAS will require you to have a BY statement.   Same requirement should apply to LAG and DIF.
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
17#
 楼主| 发表于 2004-6-6 02:40:31 | 只看该作者

To All the Others

I will not write individual comments to each of you, just a summary.

To GBT, please take a reference to the first paragraph of my comment to Genechina.  If you delete the third data line, '1 20020102 10', you will see that the program will not generate the correct answer.

To Tomwalk, Yooyok and Jimmy, please take a reference to my comment to Gsmy.  Your logic does not work for following data provided by Willon:
2 20020102 8
2 20020103 14
2 20020104 8
The episode for VOL=8 is not continuous here.  

For yooyok, in PROC SQL, you can say

proc sql;
create table a as
select min(date) as sdate format=mmddyy10.
from tem;
quit;
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
18#
 楼主| 发表于 2004-6-6 08:42:40 | 只看该作者

to xic

谢谢 xic。其实昨天在sasor就知道自己做错了。本来要删除我的帖子的,想想算了就留在上面吧。
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
19#
 楼主| 发表于 2004-6-7 08:56:56 | 只看该作者

更正

多谢xic的指点,我将源程序中
if id=lag(id) and vol=lag(vol) then fflag=1;
改为
if id=lag(id) and vol=lag(vol)and date=lag(date)+1 then fflag=1;
应该没问题
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
20#
 楼主| 发表于 2004-6-7 10:43:20 | 只看该作者

to xic

我提交的code中,有个错误。
date t2;set t2;....

应该改为date t2;set t;
多谢xic的指出。

关于逻辑是否存在错误,要看具体要求。
“要求找出以下数据中,各类Id的一段段相同vol的开始时间与结束时间。”

如果对于非连续日期的纪录,允许保留各类Id的一段段相同vol的开始时间与结束时间的话,应该是没有问题的。我想。

除非要求对非连续日期的数据,分开统计。
比如:
1 20020101 10
1 20020103 10

要求整理为:
id vol startdate enddate
1 10 20020101 20020101
1 10 20020103 20020103
这样的话,可能程序会比较复杂。一时考虑不出。

关于merge语句的使用,的确当未使用正确的by语句时,比较危险。
我感觉用好的话,还是比较方便的。

个人意见,仅供参考。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|手机版|Archiver|SAS中文论坛  

GMT+8, 2026-2-5 21:35 , Processed in 0.069275 second(s), 18 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表