SAS累计计数(按唯一ID和日期)

时间:2020-06-04 02:50:14

标签: sas

我有一个像下面这样的数据集

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

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

Cust_count  Vistited_Date
3           7-Feb-20
2           14-Feb-20

2020年2月7日有3个唯一的客户,而 2020年2月14日只有2个,因此客户1234已经造访了

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

很抱歉,我的问题还不够清楚,如有必要,我可以提供更多详细信息。

谢谢!

5 个答案:

答案 0 :(得分:3)

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

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

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

可以使用hash进行跟踪,并且可以在每个组的 DOW 循环中执行条件计数。 DOW循环将SET语句放在显式DO内。

示例:

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个“记录”,其中3,000 groups个中的1,000 dates,ID重用率为10%(因此,不同的ID将为〜2.7M)。


%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;

答案 1 :(得分:3)

import os
import time
from datetime import datetime
dat =['Fri May 29 20:47:53 2020']
for i in dat:
    print(datetime.strptime(i,'%a %B %d %H:%M:%S %Y').date())

答案 2 :(得分:2)

如果您的数据未排序并且您喜欢SQL,则此解决方案对您同样有好处,而且非常简单:

    /* 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
    */

答案 3 :(得分:1)

另一种方法,因为我不太了解哈希。 > _ << / p>

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 want;
    length Used $200.;
    retain Used;
    set have;
    by Date;

    if first.Date then count = .;
    if not find(Used,cats(ID)) then do;
        count + 1;
        Used = catx(',',Used,ID);
    end;
    if last.Date;
    put Date= count=;
run;

答案 4 :(得分:1)

如果您对处理速度不是很在意,并希望简单一些:

proc sort data=have;
   by id date;
** Get date of each customer's first unique visit **;
proc sort data=have out=first_visit nodupkey;
   by id;

proc freq data=first_visit noprint;
   tables date /out=want (keep=date count);
run;