Date 寻找一种更有效的方法,根据SAS中的日期和分组变量重新构造数据
原始数据:Date 寻找一种更有效的方法,根据SAS中的日期和分组变量重新构造数据,date,sas,retain,Date,Sas,Retain,原始数据: subject medgrp stdt endt 1 A 7/1/2014 7/31/2014 1 A 7/29/2014 8/30/2014 1 B 7/1/2014 8/15/2014 1 C 8/1/2014 9/1/2014 2 A 4/15/2014 5/15/2014 2 A 5/10/2
subject medgrp stdt endt
1 A 7/1/2014 7/31/2014
1 A 7/29/2014 8/30/2014
1 B 7/1/2014 8/15/2014
1 C 8/1/2014 9/1/2014
2 A 4/15/2014 5/15/2014
2 A 5/10/2014 6/10/2014
2 A 6/5/2014 6/15/2014
2 A 7/1/2014 8/1/2014
3 A 6/5/2014 6/15/2014
3 A 6/16/2014 8/1/2014
重组数据:
subject med_pattern stdt_new endt_new
1 A*B 7/1/2014 7/31/2014
1 A*B*C 8/1/2014 8/15/2014
1 A*C 8/16/2014 8/30/2014
1 C 8/31/2014 9/1/2014
2 A 4/15/2014 6/15/2014
2 A 7/1/2014 8/1/2014
3 A 6/5/2014 8/1/2014
我能够通过将所有记录的stdt
输出到endt
将原始数据转换为重新结构化的数据,然后为每个subject/medgrp
保留一个日期,改革日期周期并创建变量med_模式
然而,这种方法需要很长时间才能运行,尤其是对于大数据(>3m条记录)
如果您有任何建议可以提高效率,我们将不胜感激 通过
subject
您可以使用日期键控的多数据散列来跟踪stdt
和endt
定义的日期范围内每个日期的medgrp
活动。哈希的迭代将允许您计算medgrps交叉值
数据已经存在;输入
受试者medgrp$stdt:mmddyy8。完:mmddyy8 ;。;格式stdt endt mmddyy10。;
数据线;
1A 2014年1月7日2014年7月31日
1A 2014年7月29日2014年8月30日
1B 2014年1月7日2014年8月15日
1A 2014年7月15日2014年7月15日
1 C 2014年1月8日2014年1月9日
2A 2014年4月15日2014年5月15日
2A 2014年10月5日2014年10月6日
2 A 2014年6月5日2014年6月15日
2A 2014年1月7日2014年1月8日
3 A 2014年6月5日2014年6月15日
3 A 2014年6月16日2014年8月1日
;
数据交叉点按日期/视图=交叉点按日期;
如果为0,则设置为have;*准备PDV;
如果,那就做;;
声明哈希dg(多数据:'yes',顺序:'a');%*主题日期的第一个哈希;
defineKey总经理(“日期”);
dg.defineData(“日期”、“medgrp”);
dg.defineDone();
电话丢失(日期);格式日期adate cdate mmddyy10。;
声明散列交叉(有序:'a');%*用于重复删除MEDGRP列表的第二个哈希;
crossing.defineKey(“medgrp”);
交叉。定义数据(“medgrp”);
crossing.defineDone();
宣布hiter dgi(“dg”);
宣布希特勒十一世(“穿越”);
结束;
dg.clear();
直到(最后一个主题)为止逐个处理主题;
集有;
按科目划分;
do日期=从stdt到endt;*在日期范围内使用medgrp加载多数据哈希;
dg.add();
结束;
结束;
*检查受试者活动的每个日期;
adate=。;
cdate=-1e9;
当(dgi.next()=0)时,do _i_=1乘以1;
如果日期相等
然后继续;*hiter over multi data将返回每个节点;
else adate=日期;*跟踪活动日期;
*加载哈希以消除medgrp在日期上的重复跟踪;
交叉。清除();
doi=1乘1,而(dg.dou over()=0);
交叉。替换();
结束;
*计算日期上的交叉表示,A*B*。。。通过遍历第二个散列;
席();长度交叉20美元;
交叉=medgrp;
do while(0=席.nEXT());
交叉=catx(“*”,交叉,medgrp);
结束;
如果日期-cdate>1,则集群+1;%*基于数据连续性的航迹聚类;
cdate=日期;
输出;*如果您可以发布用于转换原始数据的代码,这将非常有帮助。请将您的问题更新为文本而不是图像形式的示例数据。您是否有SAS/CONNECT?您已经有了一些产生正确输出的逻辑,因此,如果您将数据拆分为n个部分并并行处理它们,您可以在不需要太多额外工作的情况下将其速度提高n倍。感谢您向我介绍这种方法。我从未遇到过多数据散列。它确实有效,但我唯一关心的是,它比我最初的方法需要更多的时间来运行。我使用10k数据集对其进行了测试。我的方法运行了6.61秒,而这一次运行了21秒。我很惊讶它需要这么长的时间,但没有任何数据进行故障排除。也许有些日期范围很大?10K数据集中有多少主题?受试者将展示哪些日期范围?你能显示你10公里跑步的记录吗?它会告诉你视图发送了多少行?一个可能的怀疑是哈希重置dg.CLEAR()
和crossing.CLEAR()
非常耗时。有一些基于直接索引数组的版本,如果您允许对最大总日期范围、组数和交叉主题体验设置先决条件,则速度可能会快得多如果您想提供10K样本数据,可以链接到google doc或pastebin.com条目
data have; input
subject medgrp $ stdt: mmddyy8. endt: mmddyy8.; format stdt endt mmddyy10.;
datalines;
1 A 7/1/2014 7/31/2014
1 A 7/29/2014 8/30/2014
1 B 7/1/2014 8/15/2014
1 A 7/15/2014 7/15/2014
1 C 8/1/2014 9/1/2014
2 A 4/15/2014 5/15/2014
2 A 5/10/2014 6/10/2014
2 A 6/5/2014 6/15/2014
2 A 7/1/2014 8/1/2014
3 A 6/5/2014 6/15/2014
3 A 6/16/2014 8/1/2014
;
data crossings_by_date / view=crossings_by_date;
if 0 then set have; * prep PDV;
if _n_ then do;
declare hash dg(multidata:'yes', ordered:'a'); %* 1st hash for subject dates;
dg.defineKey('date');
dg.defineData('date', 'medgrp');
dg.defineDone();
call missing (date); format date adate cdate mmddyy10.;
declare hash crossing(ordered:'a'); %* 2nd hash for deduping a list of medgrps ;
crossing.defineKey('medgrp');
crossing.defineData('medgrp');
crossing.defineDone();
declare hiter dgi('dg');
declare hiter xi('crossing');
end;
dg.clear();
do _n_ = 1 by 1 until (last.subject); * process subjects one by one;
set have;
by subject;
do date = stdt to endt; * load multidata hash with medgrp over date range;
dg.add();
end;
end;
* examine each date in which subject had activity;
adate = .;
cdate = -1e9;
do _i_ = 1 by 1 while (dgi.next() = 0);
if date eq adate
then continue; * hiter over multi-data will return each node;
else adate = date; * track activity date;
* load hash to dedupe tracking of medgrp on date;
crossing.clear();
do _i_ = 1 by 1 while (dg.do_over() = 0);
crossing.replace();
end;
* compute crossing representation on date, A*B*... by traversing 2nd hash;
xi.first(); length cross $20;
cross = medgrp;
do while(0 = xi.next());
cross = catx('*',cross,medgrp);
end;
if date - cdate > 1 then cluster + 1; %* track cluster based on date continuities;
cdate = date;
output; * <------------ view OUTPUT;
end;
keep subject date cross cluster;
run;
* 2nd data step processes view (1st data step);
* determine when date continuity ends or medgrp changes;
data want;
length subject 8 medgrps $20;
format stdt endt mmddyy10.;
do _n_ = 1 by 1 until (last.medgrps);
set crossings_by_date (rename=cross=medgrps);
by cluster medgrps notsorted;
if stdt = . then
stdt = date;
end;
endt = date;
keep subject medgrps stdt endt;
run;