SAS中文论坛

 找回密码
 立即注册

扫一扫,访问微社区

查看: 1136|回复: 6
打印 上一主题 下一主题

请问data step怎么实现count distinct及引申问题

[复制链接]

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
楼主
 楼主| 发表于 2009-8-11 20:55:38 | 只看该作者

请问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就产生一个新表, 我想让它就在原表一张表里更新, 怎么做?


十分感谢.
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
沙发
 楼主| 发表于 2009-8-12 09:29:24 | 只看该作者

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]
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
板凳
 楼主| 发表于 2009-8-12 17:17:57 | 只看该作者

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实现?

谢谢.
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
地板
 楼主| 发表于 2009-8-12 18:02:44 | 只看该作者

Re: 请问data step怎么实现count distinct及引申问题

Sorry,是我没看明白,太难了,我做不了.
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
5#
 楼主| 发表于 2009-8-12 20:59:43 | 只看该作者

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]
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
6#
 楼主| 发表于 2009-8-14 03:31:10 | 只看该作者

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
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

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

Re: 请问data step怎么实现count distinct及引申问题

非常感谢你, 4772814!
两种方法都很简洁明了, 我对比了两种方法, 对1千万行的数据, data step+hash函数只用了30秒,
而sql用了7个小时, 还是data步快啊, 请问哪里可以找到像这样的专门解决实际问题的高级data step编程呢?
再次感谢.

sun, 也谢谢你, 不过你的程序我没太看懂:(
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-2-5 23:10 , Processed in 0.068634 second(s), 20 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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