SAS中文论坛

 找回密码
 立即注册

扫一扫,访问微社区

查看: 1138|回复: 3
打印 上一主题 下一主题

SAS程序员测试(三)

[复制链接]

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
楼主
 楼主| 发表于 2004-9-16 12:57:10 | 只看该作者

SAS程序员测试(三)

[b:27bd0]数据:[/b:27bd0]一个表中含有hasillness,sex,age,earning……等字段,其中hasillness中为1的记录有m条,为0的有n条;
[b:27bd0]问题:[/b:27bd0]从hasillness=0的记录集中[color=red:27bd0]随机[/color:27bd0]取出n条与hasillness=1的全部数据[color=red:27bd0]配对[/color:27bd0],配对因素为sex,age,earning。
[b:27bd0]引入一个概念,“层内组”:[/b:27bd0]hasillness=1或0的记录集中sex,age,earning相同的记录组成的组,分别记为层内组_1与层内组_0。
1)当"层内组_1 > 层内组_0"时,扩大age的范围再配对直至配对成功。
2)当"层内组_1 <= 层内组_0"有多个配对时,应进行无返回性随机抽样。

(这应该是个分层随机抽样吧,但分层比较复杂)
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
沙发
 楼主| 发表于 2004-9-27 18:28:41 | 只看该作者

贴了好久啦,没有人回应……

郁闷了很多天,只要自己贴出来了。

思路:
1)将同一性别、年龄和收入的人分在一组;
2)使用循环读取各组,并分别将各组导出并进行抽样、导出样本:
  当“0<有病人数<=无病人数”:根据有病人数的个数对无病人群进行抽样;
  当“有病人数>无病人数”:放宽年龄条件直至“有病<=无病”再进行抽样(代码中用简单提示来代替)。
3)合并导出数据。


[code:a8b0a]
/*以下将数据分组*/
proc sort data=data_1;
    by age sex earning;
data data_1;
    retain no 0;
    set data_1;
    by age sex earning;
    flag=no;
    if last.earning then no+1;
run;

%macro app;
    %let j=0;
   
    proc sql noprint;
        select max(flag) into :num_flag from data_1;/*对定义flag的最大值*/

    %do i=0 %to &num_flag;/*组的循环开始*/
        proc sql noprint;
            create table temp as select * from data_1 where flag=&i;/*导出同组数据*/
            create table temp_1 as select * from temp where has_illness=0;/*导出同组数据中无病的数据*/
            select count(*) into :num_ill from temp where has_illness=1;/*定义有病的人数*/
            select count(*) into :num_noill from temp where has_illness=0;/*定义无病的人数*/

        /*0<有病<=无病时,从无病的数据文件中抽样*/
        %if &num_ill>0 and &num_ill<=&num_noill %then
            %do;
                proc surveyselect data=temp_1
                noprint
                method=srs
                n=&num_ill/*抽样的数量等于有病的人数*/
                seed=2004
                   out=Sample&j ;/*确保每次导出的数据不被覆盖*/
                run;
                %let j=%eval(&j+1);
             %end;
               
         /*有病>无病时,导出flag*/
        %if &num_ill>&num_noill %then
            %put flag;
    %end;

    /*以下合并数据*/
    %let datastr=sample0;
    %do h=1 %to %eval(&j-1);
        %let datastr=%str(&datastr sample&h);/*形成要合并的数据文件*/
    %end;

    data illness_control;
        set &datastr;
    run;
%mend app;
%app;
[/code:a8b0a]
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
板凳
 楼主| 发表于 2004-9-29 18:25:53 | 只看该作者

优化

以上代码中存在两个可以优化的问题
1、如果区组过多,而且在很多组中没有一个患病,导致了大量的执行时间浪费。
办法:先剔除没有患者的组,再重新区组、进行后继程序。

2、如果区组过多,获得的sample必将很多,合并这些sample也要花费大量的执行时间。
办法:使用insert into temp_data select * from sample,将每次循环抽样的数据导入temp_data
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
地板
 楼主| 发表于 2004-12-13 14:51:22 | 只看该作者

sql(抽样的时候只是按产生的随机数大小而定)

proc sql;
create table temp1 as
select name as name1,sex as sex1,age as age1,height as height1,weight as weight1 from sasuser.class where sex='F';
create table temp2 as
select name as name2,sex as sex2,age as age2,height as height2,weight as weight2 from sasuser.class where sex='M';

run;

proc sql;
create table temp3 as
select a.*,b.*,abs(b.age2 - a.age1) as diff,Normal(100) as rand  from temp1 a ,temp2 b;

run;
proc rank data=temp3 out=totaldata;
   var rand;
   ranks ranknum;
run;

proc sql;

create table temp5 as
select * from totaldata where age1<0;

run;

%macro main;
proc sql noprint;
select count(*) into :num_male from temp1;/*记录男生人数*/

  %do i=1 %to &num_male;/*按人数循环*/
   proc sql ;
       select min(diff) into:mindiff from totaldata;
           select max(ranknum) into:maxrand from totaldata where diff=&mindiff;
       insert into temp5 select * from totaldata where diff=&mindiff and ranknum =&maxrand;
           delete from totaldata where name1 in (select name1 from temp5) or name2 in (select name2 from temp5);
  %end;

%mend main;

%main;



说明:数据和使用的变量不同,不过基本做法应该都是一样的,结果文件是temp5
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-6-8 15:45 , Processed in 0.070759 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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