SAS中文论坛

 找回密码
 立即注册

扫一扫,访问微社区

查看: 1057|回复: 4
打印 上一主题 下一主题

请教一个简单的问题,这种循环如何实现。

[复制链接]

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
楼主
 楼主| 发表于 2004-4-13 11:27:33 | 只看该作者

请教一个简单的问题,这种循环如何实现。

有一个表,假设内容为
id,  age,month,region
121, 18 , 1, A
122, 17 , 1, B
125, 15 , 2, A
150, 30 , 5 , B
.....

想统计这样几个值:对所有ID中有‘21’的记录
1、各region每月的记录数(也就相当于region A ,month(1)=1);
2、以5为一个段,各年龄段每month的记录数(比如说15-19年龄段,month(1)=3);
3、各年龄段、各region每month的记录数(如:15-19,A ,month(1)=1)。结果送入一新表中。

从理论上讲,这个程序不难,但我是新接触SAS,对语法不熟悉。不知道如何实现循环。请哪位大侠指点一下,最好明确一下语法的使用。过了这关,我一定努力学习SAS,回报社会。

我的想法:先求出(3)的结果,利用它再求1和2
我的伪代码:求(3)结果:
for i= 1 to 12
for k=0 to 15 /*age group*/
  select count(1) as number ,i as month , k as age_group, 'A' as region
    where month=i , int(age/5)=k, region='a',index(id,'21') ne 0;
end for // for k
end for // for i
.....same code to other regions like B C D...

也想用proc freq实现,但不知道这么多条件怎么实现。
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
沙发
 楼主| 发表于 2004-4-13 12:50:51 | 只看该作者
随便demo一个,要求id中char型的,否则要改一改。

proc format;
value age  1-5='1-5'     6-10='6-10'
          11-15='11-15' 16-20='16-20'
          21-25='21-25' 26-30='26-30';
;
data tem;
input id $ age month region $;
age1=put(age,age.);
cards;
121 18 1 A
121 17 1 B
121 16 2 A
121 17 2 A
150 30 5 B
;run;

proc sql;
create table result1 as
  select age1 as age,region,month,count(1) as number from tem
  where index(id,'21')>0 group by age1,region,month;
quit;
proc print;run;
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
板凳
 楼主| 发表于 2004-4-13 13:05:16 | 只看该作者

proc freq 过程实现。

/**********************************************************/
proc format;
   value age
   1 - 5='1'
   6 -10='2'
   10-15='3'
   16-20='4'
   21-25='5'
   26-30='6'
   31-35='7'
;

data tem;
input id $  age month region $;
age_1=put(age,age.);
cards;
121  18   1   A
122  17   1   B
125  15   2   A
150  30   5   B
121  14   5   A
121  9    4   B
121  19   1   B
121  17   1   A
;
run;

/********************************************************/
proc freq data=tem noprint;
table age_1*region*month/norow nocol nopercent out=tem1;
where index(id,'21') ne 0;
run;
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
地板
 楼主| 发表于 2004-4-13 19:11:45 | 只看该作者
假设数据源是这样的:

data source;
input id age month region $;
cards;
121 18 1 A
121 17 1 B
121 16 2 A
121 17 2 A
150 30 5 B
;
run;

造个format从1到100,每5个一段:
data format;
length start end label $10;
fmtname = "age_grp";
type = "N";
do i = 1 to 100 by 5;
        start = trim(left(i));
        end = trim(left(i + 4));
        label = trim(start)||"-"||trim(end);
        output;
end;
start = "other";
end = start;
label = start;
output;
drop i;
run;

proc format cntlin=format;
run;

用Proc Summary把 region*month*age month*age region 三个层次的汇总一次生成:
proc summary data=source(where=(index(trim(left(id)),'21')>0)) chartype;
class region month age;
types region*month*age month*age region;
output out=summary;
format age age_grp.;
run;

打印结果:
proc print data=summary(keep=region age month _freq_ _type_ where=(_type_="111"));
run;

proc print data=summary(keep=age month _freq_ _type_ where=(_type_="011"));
run;

proc print data=summary(keep=region _freq_ _type_ where=(_type_="100"));
run;

或者用“小猪”网友的算法:
proc freq data=source(where=(index(trim(left(id)),'21')>0))  noprint;
table age*region*month/norow nocol nopercent out=tem1;
table age*month/norow nocol nopercent out=tem2;
table region*month/norow nocol nopercent out=tem3;
format age age_grp.;
run;

提示:
用trim(left(id))不管id是否字符型都可以使用index(trim(left(id)),'21')>0

用format age age_grp.在过程步里动态转换format,不需要专门生成这个列

一般来说,Proc summary在功能上和效率上比Proc Sql汇总及Proc Freq要好一些。
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
5#
 楼主| 发表于 2004-4-13 21:06:48 | 只看该作者
收到!请继续指教!
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-1-10 00:35 , Processed in 0.757716 second(s), 20 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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