我有如下所示的数据
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-207-2020年2月-2020年有3个独特的客户,而14-2月-2020只有2家,因此客户1234已经访问了。
有人知道我如何在这种情况下开发数据集吗?
如果我的问题不够清楚,很抱歉,如果需要的话,我可以提供更多的细节。
谢谢!
发布于 2020-06-04 04:47:35
注意:@draycut的答案具有相同的逻辑,但速度更快,我将解释原因。
@draycut的代码使用一种哈希方法add()__,它使用返回代码作为条件增量的测试。我的代码使用check()测试条件增量,然后使用add (永远不会失败)进行跟踪。一种方法可以被认为在性能上比其他方法快15%到40% (取决于组数、组大小和id重用率)。
您需要跟踪以前所有组中发生的ID,并从当前组计数中排除跟踪的ID。
跟踪可以用hash完成,条件计数可以在每组的陶氏周期中执行。陶氏循环将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个“记录”,1,000个groups的3,000个dates,10%的id重用(因此不同的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;发布于 2020-06-04 07:43:58
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;发布于 2020-06-09 21:02:59
如果您的数据没有排序,并且您喜欢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
*/https://stackoverflow.com/questions/62186055
复制相似问题