SAS中文论坛

标题: 请问data step怎么实现count distinct及引申问题 [打印本页]

作者: shiyiming    时间: 2009-8-11 20:55
标题: 请问data step怎么实现count distinct及引申问题
现在有每个user_id 的交往圈数据, 每个user_id 对应多个friend_id,
我先按交往圈个数从高往低排序, 然后从第n个(n=1到N)user_id开始统计第1个到第n个user_id的friend_id中所有不重复的个数count_num, 并将count_num作为一个变量接在相应user_id后面.

现在的问题是:
1, 怎么用data step实现, 请问data step能count distinct么? 如果不能, 有什么其他折中的办法?
2, proc sql中可以count distinct, 但怎么将带sql的macro循环起来? 我写的proc sql循环可以统计累计不重复个数, 但循环几次就生成几张新表, 因为每个proc sql就产生一个新表, 我想让它就在原表一张表里更新, 怎么做?


十分感谢.
作者: shiyiming    时间: 2009-8-12 09:29
标题: Re: 请问data step怎么实现count distinct及引申问题
[quote:5gvm15u9]然后从第n个(n=1到N)user_id开始统计第1个到第n个user_id的friend_id中所有不重复的个数count_num[/quote:5gvm15u9]
不太明白
[code:5gvm15u9]/* 创建模拟数据 */
data raw_ds(keep=user_id friend_id);
   seed=123;
   do i=1 to 10;
      user_id=i;
      friend_id=ceil(10*ranuni(seed));
      do j=1 to ceil(10*ranuni(seed));
         friend_id+1;
         output;
      end;
   end;
run;

/* by user_id计算friend数量 */
data final_ds;
   friend_count=0;
   do _n_=1 by 1 until(last.user_id);
      set raw_ds;
      by user_id;
      friend_count+1;
   end;
   do _n_=1 to _n_;
      set raw_ds;
      by user_id;
          output;
   end;
run;

/* 按friend数量降序 */
proc sort data=final_ds;
   by descending friend_count user_id;
run;

/* 为user_id创建新序号 */
data final_ds;
   sort_id+1;
   do _n_=1 by 1 until(last.user_id);
      set final_ds;
      by descending friend_count user_id;
      output;
   end;
run;

/* 取前n个user_id的friend_id的count */
%let n=3;
proc sql;
        create table _temp_repfid as
                select friend_id, count(friend_id) as repeat_count
                        from final_ds
                        where sort_id<=&n
                        group by friend_id
                        order by friend_id;
quit;

/* _iorc_ merge */
proc datasets nolist;
        modify _temp_repfid;
        index create friend_id/unique;
quit;

data final_ds;
        set final_ds;
        set _temp_repfid key=friend_id/unique ;
        if _iorc_ ne 0 then do;
                _iorc_=0;
                _error_=0;
                repeat_count=.;
        end;
        if sort_id>&n then repeat_count=.;
run;

/* 计算非重复的friend数量 */
data final_ds;
   do _n_=1 by 1 until(last.sort_id);
      set final_ds;
      by sort_id;
      if repeat_count=1 then count_num=sum(count_num,1);
   end;
   do _n_=1 to _n_;
      set final_ds;
      by sort_id;
          if sort_id<=&n and count_num=. then count_num=0;
          output;
   end;
run;[/code:5gvm15u9]
作者: shiyiming    时间: 2009-8-12 17:17
标题: Re: 请问data step怎么实现count distinct及引申问题
谢谢你的回复, 不过倒不是我要的结果,
不好意思,可能是我表达的不清晰, 复述一下

rank_id是按firend_id个数降序排序后的id,
对第1个rank_id统计其friend_id不重复的个数, 作为count_num,
对第2个rank_id, 统计前2个rank_id所有friend_id不重复的个数, 作为count_num,
对第3个rank_id, 统计前3个rank_id所有friend_id不重复的个数, 作为count_num,
循环至第n个rank_id, 都是统计累计friend_id不重复个数, 期望结果如下:

rank_id        friend_count        user_id             friend_id        count_num
1        3                2             3                  3       
1        3                2             4                  3       
1        3                2             5                  3       
2        2                9             7                  5       
2        2                9             8                      5
3      1               7           5           5
...


问:
1,怎么data step实现?
2,怎么proc sql实现?

谢谢.
作者: shiyiming    时间: 2009-8-12 18:02
标题: Re: 请问data step怎么实现count distinct及引申问题
Sorry,是我没看明白,太难了,我做不了.
作者: shiyiming    时间: 2009-8-12 20:59
标题: Re: 请问data step怎么实现count distinct及引申问题
[code:17y9krj9]data a;
input rank_id friend_count user_id friend_id count_num ;
cards;
1 3 2 3 3
1 3 2 4 3
1 3 2 5 3
2 2 9 7 5
2 2 9 8 5
3 1 7 5 5
;
run;

data m;
set a;
by rank_id;
if _n_=1 then do;
declare hash myhash();
myhash.definekey("friend_id");
myhash.definedone();
             end;
if myhash.find(key:friend_id) ne 0 then  rc=myhash.add() ;

if last.rank_id then do;
     ncount_num=myhash.num_items;
         output;
                   end;
keep rank_id ncount_num        ;
run;


proc sql;
select distinct rank_id,
( select count( distinct friend_id) from a  b1 where b1.rank_id<=b2.rank_id )as ncount
from  a b2;
quit;
[/code:17y9krj9]
作者: shiyiming    时间: 2009-8-14 03:31
标题: Re: 请问data step怎么实现count distinct及引申问题
/* ´´½¨Ä£ÄâÊý¾Ý  */
data raw_ds(keep=user_id friend_id);
   seed=123;
   do i=1 to 10;
      user_id=i;
      friend_id=ceil(10*ranuni(seed));
      do j=1 to ceil(10*ranuni(seed));
         friend_id+1;
         output;
      end;
   end;
run;

* the code above by hopewell;

* if this is what you want;
%macro ct;
        proc sql;
                select distinct user_id into: users separated by ' '
                        from raw_ds;
                %let n=&sqlobs;
                create table result as
                        select distinct user_id, count(distinct friend_id) as count_n
                                from (select distinct  user_id,  friend_id
                                                        from raw_ds
                                                        where user_id in (%scan(&users,1)));
                %do i=2 %to &n.;
                        %let usid = %scan(&users,&i);
               
                                        select count(distinct friend_id) into:n
                                                from raw_ds
                                                where user_id in
                                                        (%scan(&users,1)
                                                        %do k=2 %to &i;
                                                                %scan(&users,&k)  
                                                        %end;
                                                        );       
                        insert into result set user_id=&usid,count_n = &n;
                %end;

        quit;

%mend;

%ct;

* this is the result;
user_id    count_n

    1          4
    2         10
    3         10
    4         10
    5         10
    6         11
    7         11
    8         12
    9         13
   10         13
作者: shiyiming    时间: 2009-8-14 20:58
标题: Re: 请问data step怎么实现count distinct及引申问题
非常感谢你, 4772814!
两种方法都很简洁明了, 我对比了两种方法, 对1千万行的数据, data step+hash函数只用了30秒,
而sql用了7个小时, 还是data步快啊, 请问哪里可以找到像这样的专门解决实际问题的高级data step编程呢?
再次感谢.

sun, 也谢谢你, 不过你的程序我没太看懂:(




欢迎光临 SAS中文论坛 (https://mysas.net/forum/) Powered by Discuz! X3.2