我的数据集在某些情况下被分成多行,我需要找到这些实例并重新组合这些行。这需要我计算组和子组内数据集中日期之间的差异,然后有效地"合并行"。如果开始日期和结束日期之间的差异为1天或以下。我的数据集是这样的:
ID | Start | End | Place |
1 | 01-01-2020 | 31-03-2020 | Street 1 |
1 | 01-04-2020 | 31-07-2020 | Street 1 |
1 | 01-08-2020 | 31-12-2020 | Street 1 |
1 | 01-01-2021 | 31-03-2021 | Street 2 |
2 | 01-01-2020 | 31-04-2020 | Street 1 |
2 | 31-04-2020 | 31-08-2020 | Street 1 |
3 | 01-01-2020 | 31-03-2020 | Street 1 |
我真的想输出这个:
ID | Start | End | Place |
1 | 01-01-2020 | 31-12-2020 | Street 1 |
1 | 01-01-2021 | 31-03-2021 | Street 2 |
2 | 01-01-2020 | 31-08-2020 | Street 1 |
3 | 01-01-2020 | 31-03-2020 | Street 1 |
因此,本质上,在ID组和Place子组中,如果前一个结束日期和新的开始日期之间有1或更小的差异,那么我想"组合";
我尝试创建多个数据步骤,其中我使用lag -函数很多,这似乎合理地处理了ID 2的实例,其中只有两行需要考虑。然而,对于ID 1 (Street 1),我需要有效地连接三行,我还没有找到一个好的解决方案。任何功能的建议,可能是有用的,将不胜感激!
您可以使用多步骤方法。
感谢@whymath在输入数据中发现日期问题。
data stage1;
set have;
by id place notsorted;
if first.place then
group_number+1;
run;
proc sort data=stage1 out=stage2;
by id place group_number start;
run;
data want;
do until (last.place);
set stage2;
by id place group_number;
if first.group_number then
_start=start;
if last.place then
do;
start=_start;
output;
end;
end;
drop _start group_number;
run;
id start end place
1 01-01-2020 31-12-2020 Street1
1 01-01-2021 31-03-2021 Street2
2 01-01-2020 31-08-2020 Street1
3 01-01-2020 31-03-2020 Street1
你的数据中有一些错误,我纠正它们以得到你想要的输出:
Line5:31-04-2020
→30-04-2020
Line6:31-04-2020
→01-05-2020
data have;
infile cards dlm='|';
input id start : ddmmyy10. end : ddmmyy10. place$;
format start end ddmmyyd10.;
cards;
1 | 01-01-2020 | 31-03-2020 | street 1 |
1 | 01-04-2020 | 31-07-2020 | street 1 |
1 | 01-08-2020 | 31-12-2020 | street 1 |
1 | 01-01-2021 | 31-03-2021 | street 2 |
2 | 01-01-2020 | 30-04-2020 | street 1 |
2 | 01-05-2020 | 31-08-2020 | street 1 |
3 | 01-01-2020 | 31-03-2020 | street 1 |
;
run;
你的问题的难点是根据下一行更新和输出数据。我建议你使用双组技能。
proc sort data=have;
by id place start;
run;
data want;
set have;
do i=1 to rec;
set have(rename=(id=tmpid place=tmpplace start=tmpstart end=tmpend))nobs=rec point=i;
if id=tmpid and place=tmpplace then do;
if start=tmpend+1 and _n_=i+1 then used=1;
else if end=tmpstart-1 and _n_<i then end=tmpend;
end;
end;
if used^=1;
drop tmp: used;
run;