首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >按唯一ID和日期计算的累积计数

按唯一ID和日期计算的累积计数
EN

Stack Overflow用户
提问于 2020-06-04 02:50:14
回答 5查看 519关注 0票数 1

我有如下所示的数据

代码语言:javascript
复制
Customer_ID Vistited_Date
1234        7-Feb-20
4567        7-Feb-20
9870        7-Feb-20
1234        14-Feb-20
7654        14-Feb-20
3421        14-Feb-20

假设我的输出如下所示,我正在按日期查找客户的累积唯一计数。

代码语言:javascript
复制
Cust_count  Vistited_Date
3           7-Feb-20
2           14-Feb-20

7-2020年2月-2020年有3个独特的客户,而14-2月-2020只有2家,因此客户1234已经访问了

有人知道我如何在这种情况下开发数据集吗?

如果我的问题不够清楚,很抱歉,如果需要的话,我可以提供更多的细节。

谢谢!

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2020-06-04 04:47:35

注意:@draycut的答案具有相同的逻辑,但速度更快,我将解释原因。

@draycut的代码使用一种哈希方法add()__,它使用返回代码作为条件增量的测试。我的代码使用check()测试条件增量,然后使用add (永远不会失败)进行跟踪。一种方法可以被认为在性能上比其他方法快15%到40% (取决于组数、组大小和id重用率)。

您需要跟踪以前所有组中发生的ID,并从当前组计数中排除跟踪的ID

跟踪可以用hash完成,条件计数可以在每组的陶氏周期中执行。陶氏循环将SET语句放置在显式DO中。

示例:

代码语言:javascript
复制
data have;
input ID Date: date9.; format date date11.;
datalines;
1234 7-Feb-20
4567 7-Feb-20
9870 7-Feb-20
1234 14-Feb-20
7654 14-Feb-20
3421 14-Feb-20
;

data counts(keep=date count);
  if _n_ =  1 then do;
    declare hash tracker();
    tracker.defineKey('id');
    tracker.defineDone();
  end;  

  do until (last.date);
    set have;
    by date;

    if tracker.check() ne 0 then do;
      count = sum(count, 1);
      tracker.add();
    end;
  end;
run;

原始性能基准-没有磁盘io,cpu需要填充数组之前进行散列,所以这些性能组件是组合的。

根性能是将新项添加到散列中的速度。

模拟3,000,000个“记录”,1,000个groups的3,000个dates,10%的id重用(因此不同的id将是~2.7M)。

代码语言:javascript
复制
%macro array_fill (top=3000000, n_group = 1000, overlap_factor=0.10);
  %local group_size n_overlap index P Q;

  %let group_size = %eval (&top / &n_group);

  %if (&group_size < 1) %then %let group_size = 1;

  %let n_overlap = %sysevalf (&group_size * &overlap_factor, floor);

  %if &n_overlap < 0 %then %let n_overlap = 0;

  %let top = %sysevalf (&group_size * &n_group);

  P = 1;
  Q = &group_size; 

  array ids(&top) _temporary_;

  _n_ = 0;
  do i = 1 to &n_group;
    do j = P to Q;
      _n_+1;
      ids(_n_) = j;
    end;
    P = Q - &n_overlap;
    Q = P + &group_size - 1;
  end;
%mend;

options nomprint;

data _null_ (label='check then add');
  length id 8;

  declare hash h();
  h.defineKey('id');
  h.defineDone();

  %array_fill;

  do index = 1 to dim(ids);
    id = ids(index);

    if h.check() ne 0 then do;
      count = sum(count,1);
      h.add();
    end;
  end;

  _n_ = h.num_items;
  put 'num_items=' _n_ comma12.;
  put index= comma12.;

  stop;
run;


data _null_ (label='just add');
  length id 8;                     

  declare hash h();
  h.defineKey('id');
  h.defineDone();

  %array_fill;

  do index = 1 to dim(ids);
    id = ids(index);

    if h.add() = 0 then
      count = sum(count,1);
  end;

  _n_ = h.num_items;
  put 'num_items=' _n_ comma12.;
  put index= comma12.;

  stop;
run;
票数 3
EN

Stack Overflow用户

发布于 2020-06-04 07:43:58

代码语言:javascript
复制
data have;
input Customer_ID Vistited_Date :anydtdte12.;
format Vistited_Date date9.;
datalines;
1234 7-Feb-2020
4567 7-Feb-2020
9870 7-Feb-2020
1234 14-Feb-2020
7654 14-Feb-2020
3421 14-Feb-2020
;

data want (drop=Customer_ID);
    if _N_=1 then do;
        declare hash h ();
        h.definekey ('Customer_ID');
        h.definedone ();
    end;

    do until (last.Vistited_Date);
        set have;
        by Vistited_Date;
        if h.add() = 0 then Count = sum(Count, 1);
    end;
run;
票数 3
EN

Stack Overflow用户

发布于 2020-06-09 21:02:59

如果您的数据没有排序,并且您喜欢SQL,那么这个解决方案可能对您也有好处,而且非常简单:

代码语言:javascript
复制
    /* your example  3 rows */
    data have;
    input ID Date: date9.; format date date11.;
    datalines;
    1234 7-Feb-20
    4567 7-Feb-20
    9870 7-Feb-20
    1234 14-Feb-20
    7654 14-Feb-20
    3421 14-Feb-20
    1234 15-Feb-20
    7654 15-Feb-20
    1111 15-Feb-20
    ;
    run;

    /* simple set theory. Final dataset contains your final data like results 
    below*/

    proc sql;
    create table temp(where =(mindate=date)) as select
     ID, date,min(date) as mindate from have
        group by id;
    create table final as select count(*) as customer_count,date from temp
        group by date;
    quit;

    /* results:
    customer_count  Date
    3               07.febr.20
    2               14.febr.20
    1               15.febr.20
    */
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62186055

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档