SAS中文论坛

 找回密码
 立即注册

扫一扫,访问微社区

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

一道有难度的编程题

[复制链接]

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
楼主
 楼主| 发表于 2006-3-29 02:46:46 | 只看该作者

一道有难度的编程题

一个学校有5个年级,每个年级有6个班,每个班有不同的学生人数,数据为每个学生的年级(grade)、班别(class)、姓名(name)、外语成绩(english)、总分(score)。数据集的名称为student。(student已经by grade class english ).
要求如下:
1    每个年级的每个班的学生按外语成绩的降序排列,并平均分成10组(若人数不是10的倍数,例如为n,则前9组的人数均为int[n/10],最后一组的人数为n-9*int[n/10])
2   这样就共有5*6*10=300组了,现在要计算每个组的分数,其中每个组分数=组中每个学生的总分的加权平均,权数为每个学生的外语成绩。
3   要创建一个数据集a,变量名为m1到m10,其中m1为各年级各班的第一个组的分数,即每个班最高分的那个组的分数,m2为各年级各班的第二个组的分数,以此类推。
问:程序如何实现?注意:每个班有不同的人数。
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
沙发
 楼主| 发表于 2006-3-31 08:25:01 | 只看该作者

有难度?似乎这里还有富裕呢.

有日子没来了,先贡献点儿吧.

data student;
do grade=1 to 5;
  do class=1 to 6;
    n=int(30+100*ranuni(1));
          do i=1 to n;
            name=put(grade,z2.)||'-'||put(class,z2.)||'-'||left(n);
                english=int(50+50*ranuni(2));
                score=int(100+100*ranuni(3));
                nn=int(n/10);
            output;
          end;
  end;
end;
run;

proc sort data=student;
by grade class english;
run;

data student;
retain group cnt;
set student;
by grade class english;
if first.class then do;
  group=1;
  cnt=1;
end;
else cnt=cnt+1;
output;
if cnt=nn then do;
  group=group+1;
  if group ne 10 then cnt=0;
  else cnt=-99;
end;
run;

proc means data=student mean noprint;
by grade class group;
weight english;
var score;
output out=mm mean=mean;
run;

data a(drop=_type_ _freq_ mean group);
retain m1 m2 m3 m4 m5 m6 m7 m8 m9 m10;
set mm;
by grade class group;
if first.class then do;
  m1=.; m2=.; m3=.; m4=.; m5=.;
  m6=.; m7=.; m8=.; m9=.; m10=.;
end;
select(group);
  when(1) m1=mean;
  when(2) m2=mean;
  when(3) m3=mean;
  when(4) m4=mean;
  when(5) m5=mean;
  when(6) m6=mean;
  when(7) m7=mean;
  when(8  ) m8=mean;
  when(9) m9=mean;
  when(10) m10=mean;
  otherwise;
end;
if last.class then output;
run;
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
板凳
 楼主| 发表于 2006-3-31 12:09:21 | 只看该作者

to xic

你好,非常感谢你的答案。同时,我想说明的是,数据集中本来就只有name,grade,class,english,score 这几项,其他的并没有,也就是说,编程关键在于把每个班的人数算出来并调用。而不是一开始就有每个班人数的。
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
地板
 楼主| 发表于 2006-3-31 14:59:55 | 只看该作者

to xic

你好,xic。对于你的程序最后有一个地方不是很明白,即
if last.class then output;
这一句起了好大的作用。我试过,如果去掉这一句,整个答案都不同,而且是错误的。我想问一下,这一句具体的意义是什么呢?为什么可以得到正确的答案。我自己编的程序是算到最后时用transpose的,我觉得你的编得更好,但是就是不太明白以上那一句的意思。可以解释一下吗?
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
5#
 楼主| 发表于 2006-4-3 13:29:38 | 只看该作者

真的还有富余吗?

为了体现这题目还有富余,我再努了努力.
几点说明
1.english应该是降序,但为了和XIC的结果进行比较,我也就没有加decs,你可以自己加.
2.如果严格的讲的话,XIC老兄的程序在生成测试数据集时保留了nn来做为后面程序使用的一个信息.这个过程有一点点取巧,如果原始数据没有这个变量的话,只有再加一段处理来生成它,后面的程序才能正确执行.不信大家把student数据集中的nn drop掉,看看会发生什么事.
3.最近几个论坛有意思的题目不多.希望大家能多找点有意思的题来玩玩.
[code:c4e97]proc sort data=student; /*用student数据集就可,可drop n nn*/
  by grade class english;
run;

%macro var(n);
  %do i=1 %to &n;
    ,sum(english*(group=&i)*score)/sum(english*(group=&i))as m&i
  %end;
%mend;

proc sql;
  create table temp as /*中间数据集,*/
  select grade,class,english,min(ceil((monotonic()-min(monotonic())+1)/(floor(count(*)/10))),10) as group,score
  from student
  group by grade, class
  order by monotonic()
  ;
  create table final as /*final是最后的结果集,等同于xic的结果数据集A*/
  select grade,class %var(10)
  from temp
  group by grade,class
  ;
quit;[/code:c4e97]
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-6-10 02:13 , Processed in 0.069110 second(s), 20 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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