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;作者: shiyiming 时间: 2010-6-25 21:14 标题: 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.作者: shiyiming 时间: 2010-6-26 20:53 标题: Re: 如何分组? 就是简单的聚类分析作者: shiyiming 时间: 2010-6-27 02:38 标题: Re: 如何分组? 可否帮忙写下程序,多谢了!!!作者: shiyiming 时间: 2010-7-10 07:04 标题: 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]作者: shiyiming 时间: 2010-7-10 10:20 标题: Re: 如何分组? 不明白你到底想怎么分?为什么7单独一组,为什么。。。说白了,你到底想干什么?如果类似于聚类,显然光data step是不够了。作者: shiyiming 时间: 2010-7-10 10:55 标题: 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.作者: shiyiming 时间: 2010-7-11 00:23 标题: Re: 如何分组? 解决不了。对不起作者: shiyiming 时间: 2010-7-11 09:46 标题: Re: 如何分组? 没关系。
其实我已经写好了一个code(见6楼),自己感觉还不错,但有一个情况下却很麻烦,那就是x或y的值一旦出现重复,那么我的code就必须重新run一遍,否则就有遗漏。所以,我就在想,如果在code里嵌入without replacement的程序,把已经出现最小值的一对x,y去除后再进行下一次的运行,这样就可以避免重复值(x或y)对取最小值的影响了。
所以,就想有人在我的code上做修改(嵌入实现without replacement的程序),或全新的code.
单纯的实现without replacement的程序,我用data step也实现了,但我的code主要是sql,所以,不知道如何嵌进去。
拜托各位高手。作者: shiyiming 时间: 2010-7-11 11:42 标题: Re: 如何分组? [code:2h6470s1]data raw;
input @3 x $ y;
datalines;
1 a 1
2 b 1
3 a 5
4 b 8
5 a 6
6 a 7
2 b 1
;
data a;
set raw(where=(x='a'));
id=_n_;
rename y=a_y;
run;
data b;
set raw(where=(x='b'));
run;
data out(keep=x y pair);
if _n_=1 then do;
length x $8;
declare hash h(dataset:'a',ordered:'yes');
declare hiter iter('h');
h.defineKey('id');
h.defineData('id','a_y');
h.defineDone();
call missing(id,a_y);
end;
set b;
pair=_n_;
do while(iter.next()=0);
if diff=. or abs(y-a_y) le diff then do;
diff=abs(y-a_y);
temp_ay=a_y;
a_key=id;
end;
end;
rc=h.remove(key:a_key);
output;
x='a';
y=temp_ay;
output;
run;[/code:2h6470s1]作者: shiyiming 时间: 2010-7-11 13:46 标题: Re: 如何分组? 这个问题有人工智能的意思,差不多可以认为是相亲算法。 Hopewell的hash算法很好。