SAS中文论坛

 找回密码
 立即注册

扫一扫,访问微社区

查看: 2056|回复: 14
打印 上一主题 下一主题

如何分组?

[复制链接]

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
楼主
 楼主| 发表于 2010-6-25 11:05:56 | 只看该作者

如何分组?

data a;
input id $ mod $ date;
cards;
a1 tc 3
a1 td 4
a1 td 7
a1 tc 25
a1 td 27
a2 td 1
a2 tc 17
a2 tc 18
a2 td 21
a2 td 24
a3 tc 7
a3 td 16
a3 tc 18
a3 td 24
...
;
run;
现在,我想把每个ID里的tc和td以date间隔最近的分在一组,然后再在组内求tc和td的时间差,比如在ID=a1里:
id $ mod $ date group diff
a1 tc 3  1  1
a1 td 4  1  1
a1 td 7  .  2
a1 tc 2 25 3
a1 td 2 27 3
问题:请问如何分组?
谢谢!
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
沙发
 楼主| 发表于 2010-6-25 17:00:12 | 只看该作者

Re: 如何分组?

可以先按照id先拆成数个数据集。。

然后针对每个数据集这样处理:

proc fastclus data=a1 out=b maxc=3;
        var date;
run;

proc sort data=b;
        by cluster;
run;

proc means data=b nway noprint;
        by cluster;
        class mod;
        output out=c range=range;
run;
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
板凳
 楼主| 发表于 2010-6-25 21:14:34 | 只看该作者

Re: 如何分组?

上面叙述有点错误,最后形成的dataset应该如下:
现在,我想把每个ID里的tc和td以date间隔最近的分在一组,然后再在组内求tc和td的时间差,比如在ID=a1里:
id $ mod $ date group diff
a1 tc 3  1  1
a1 td 4  1  1
a1 td 7  2  .
a1 tc 25 3  2
a1 td 27 3  2
问题:请问如何分组?
sorry and thanks again.
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
地板
 楼主| 发表于 2010-6-26 20:53:16 | 只看该作者

Re: 如何分组?

就是简单的聚类分析
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
5#
 楼主| 发表于 2010-6-27 02:38:12 | 只看该作者

Re: 如何分组?

可否帮忙写下程序,多谢了!!!
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
6#
 楼主| 发表于 2010-7-10 07:04:37 | 只看该作者

Re: 如何分组?

我写了一个code,但是有个问题,那就是一旦mod有重复值(如第2,3行的4,4),那么,我的程序就必须重新再次把剩下的record再运行一遍,否则就不完整。
所以抛砖引玉,希望有高手对我的code进行修改,或全新的code. 谢谢!!!
[code:2p8uzi98]data a0;
input mod $ bdos;
cards;
tc 1
26 4
26 4
tc 6
tc 7
tc 12
26 13
26 14
tc 17
26 19
tc 22
tc 25
26 28
tc 29
26 30
;
run;
/*add pk unid*/
data a;set a0;
pk=_n_;
unid=catx('_',mod,bdos,pk);
run;
/*split data into 2 datasets by mod*/
data a1 a2; set a;
select (mod);
when ('tc') output a1;
when ('26') output a2;
end;
run;
/*grab min(diff)*/
proc sql;
create table diff1 as
  select d1.*,abs(bdos_26-bdos_tc) as diff, catx('_',pk_tc,pk_26) as unid2,
         d2.*,(calculated diff=min(calculated diff)) as min_d
    from a1(rename=(mod=mod_tc bdos=bdos_tc pk=pk_tc)) d1,
         a2(drop=unid rename=(mod=mod_26 bdos=bdos_26 pk=pk_26)) d2
        group by unid
   having min_d^=0
    order by d1.pk_tc,unid;
quit;
proc sql;
create table diff2 as
  select d2.*,abs(bdos_26-bdos_tc) as diff,catx('_',pk_tc,pk_26) as unid2,
         d1.*,(calculated diff=min(calculated diff)) as min_d
    from a1(drop=unid rename=(mod=mod_tc bdos=bdos_tc pk=pk_tc)) d1,
         a2 (rename=(mod=mod_26 bdos=bdos_26 pk=pk_26)) d2
        group by unid
   having min_d^=0
    order by d2.pk_26,unid;
quit;
/*remove 1 record VS mulit, keep 1:1*/
proc sort data=diff1 out=diff10 nodupkey;
  by unid;
run;
proc sort data=diff2 out=diff20 nodupkey;
  by unid;
run;
/*grab 2 records with the same min(diff)*/
proc sql;
create table diff_1 as
  select d1.*
    from diff10 d1,diff20 d2
   where d1.unid2=d2.unid2;
quit;

/*add group id: g*/
data b0;
set diff_1;
g=_n_;
run;
/*separate data*/
data b1(rename=(mod_tc=mod bdos_tc=bdos) keep=mod_tc bdos_tc diff unid2 g)
     b2(rename=(mod_26=mod bdos_26=bdos) keep=mod_26 bdos_26 diff unid2 g);
  set b0;
run;

/*merge again*/
data final;
set b1 b2;
run;
/*sort dataset*/
proc sort data=final;
by g;
run;
[/code:2p8uzi98]
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

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

Re: 如何分组?

不明白你到底想怎么分?为什么7单独一组,为什么。。。说白了,你到底想干什么?如果类似于聚类,显然光data step是不够了。
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
8#
 楼主| 发表于 2010-7-10 10:55:40 | 只看该作者

Re: 如何分组?

也许之前我叙述的有些含糊,以现在的论述为准:假设一组数据如下(obs为序列号,不是变量,变量只有x和y):
obs x   y
1 a  1
2 b  1
3 a  5
4 b  8
5 a  6
6 a  7
想找出a和b间,y值差距最小的一对对。
比如:第一行a和第二行b,他们对应的y值之差(绝对值)(1-1=0)最小,除此以外,第一行a和任何其他b间的y值之差总大于0,任何第二行b和其他任何a间的差大于0,那么,
obs x   y
1  a  1
2  b  1
就是距离最近的一对。
同样,第四行b和第六行a间的距离最近,(8-7=1)为最小,第四行b和任何其他a间的y值之差总大于1,任何第六行a和其他任何b间的差大于0,那么,
obs  x   y
4  b  8
6  a  7
就是距离最近的一对。
最后想得到的结果就是:
obs x   y  pair
1  a  1   1
2  b  1   1
4  b  8   2
6  a  7   2
这样叙述,不知道还有没有疑义。
thanks.
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
9#
 楼主| 发表于 2010-7-11 00:23:04 | 只看该作者

Re: 如何分组?

解决不了。对不起
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
10#
 楼主| 发表于 2010-7-11 09:46:35 | 只看该作者

Re: 如何分组?

没关系。
其实我已经写好了一个code(见6楼),自己感觉还不错,但有一个情况下却很麻烦,那就是x或y的值一旦出现重复,那么我的code就必须重新run一遍,否则就有遗漏。所以,我就在想,如果在code里嵌入without replacement的程序,把已经出现最小值的一对x,y去除后再进行下一次的运行,这样就可以避免重复值(x或y)对取最小值的影响了。
所以,就想有人在我的code上做修改(嵌入实现without replacement的程序),或全新的code.
单纯的实现without replacement的程序,我用data step也实现了,但我的code主要是sql,所以,不知道如何嵌进去。
拜托各位高手。
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-2-4 04:57 , Processed in 0.070555 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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