如何在 SAS 中为每个 ID 插入新行和值
How to insert new rows and values for each ID in SAS
我有 3 个变量:ID、天数和温度。对于每个条目,我需要为每个 ID 插入额外天数的行,并且我需要温度在这些行之间进行传递。
目标是让每个 ID 都有完整的连续几天具有相同的温度。这是我的:
ID day temp
1001 68 16
1001 73 14
1002 85 17
1002 89 15
1003 91 18
1004 97 19
1004 99 20
1004 106 12
1005 109 15
1006 111 18
1006 115 19
1006 120 20
1006 122 21
这就是我想要的:
ID day temp
1001 68 16
1001 69 16
1001 70 16
1001 71 16
1001 72 16
1001 73 14
1001 74 14
1001 75 14
1001 76 14
1001 77 14
1001 78 14
1001 79 14
1001 80 14
1001 81 14
1001 82 14
1001 83 14
1001 84 14
1002 85 17
1002 86 17
1002 87 17
1002 88 17
1002 89 15
1002 90 15
1003 91 18
1003 92 18
1003 93 18
1003 94 18
1003 95 18
1003 96 18
1004 97 19
1004 98 19
1004 99 19
proc sort data=have;
by ID;
run;
data want;
set have;
retain temp ID;
day=day +1;
if first.day then temp= temp+0;
end;
run;
我希望结果是这样的:
ID day temp
1001 68 16
1001 69 16
1001 70 16
1001 71 16
1001 72 16
1001 73 14
1001 74 14
1001 75 14
1001 76 14
1001 77 14
1001 78 14
1001 79 14
1001 80 14
1001 81 14
1001 82 14
1001 83 14
1001 84 14
1002 85 17
1002 86 17
1002 87 17
1002 88 17
1002 89 15
1002 90 15
1003 91 18
1003 92 18
1003 93 18
1003 94 18
1003 95 18
1003 96 18
1004 97 19
1004 98 19
1004 99 19
但不知何故,我仍然得到我试图更改的旧数据。任何帮助将不胜感激。谢谢
除了最后一个条目似乎与您的逻辑不一致外,以下代码应该可以满足您的需求:
1004 99 19
结果是:
1004 99 20
根据你的逻辑。
proc sort data=have;
by ID day;
run;
data want;
merge have have (firstobs=2 rename=(id=id2 day=day2 temp=temp2));
output;
if (day2 > day) then do;
do while (day < day2 - 1);
day + 1; output;
end;
end;
keep id day temp;
run;
一个稳健的解决方案将在每个 id
组的开始重置迭代。您的示例数据不显示连续组的开始日期早于前一组的情况。如果不测试 id 组的开始(或在组内),结果可能与预期不同。
示例 1:1 与从 obs=2
开始的第二个自我合并,以提供来自 next 的 lead 值排。数据已用组 id=1007
和 id=1009
进行了修改,因此需要 重置 。组within-ness条件用id=lead_id
测试
data have; input
ID day temp; datalines;
1001 68 16
1001 73 14
1002 85 17
1002 89 15
1003 91 18
1004 97 19
1004 99 20
1004 106 12
1005 109 15
1006 111 18
1006 115 19
1006 120 20
1006 122 21
1007 1 1
1007 15 0
1007 16 2
1007 20 5
1008 35 12
1008 37 14
1008 45 20
run;
data want (drop=lead:);
merge have have(keep=day id rename=(id=lead_id day=lead_day) firstobs=2);
* by is not used for a 1:1 merge;
if id=lag(id) and day < lag(day) then do;
put "ERR" "OR: Stopping because days are not ordered within " ID= "at " day= ;
stop;
end;
if (id=lead_id) then do day=day to lead_day-1;
output; * fill-in rows with same temp;
end;
else
output; * final row of group;
run;
我有 3 个变量:ID、天数和温度。对于每个条目,我需要为每个 ID 插入额外天数的行,并且我需要温度在这些行之间进行传递。
目标是让每个 ID 都有完整的连续几天具有相同的温度。这是我的:
ID day temp
1001 68 16
1001 73 14
1002 85 17
1002 89 15
1003 91 18
1004 97 19
1004 99 20
1004 106 12
1005 109 15
1006 111 18
1006 115 19
1006 120 20
1006 122 21
这就是我想要的:
ID day temp
1001 68 16
1001 69 16
1001 70 16
1001 71 16
1001 72 16
1001 73 14
1001 74 14
1001 75 14
1001 76 14
1001 77 14
1001 78 14
1001 79 14
1001 80 14
1001 81 14
1001 82 14
1001 83 14
1001 84 14
1002 85 17
1002 86 17
1002 87 17
1002 88 17
1002 89 15
1002 90 15
1003 91 18
1003 92 18
1003 93 18
1003 94 18
1003 95 18
1003 96 18
1004 97 19
1004 98 19
1004 99 19
proc sort data=have;
by ID;
run;
data want;
set have;
retain temp ID;
day=day +1;
if first.day then temp= temp+0;
end;
run;
我希望结果是这样的:
ID day temp
1001 68 16
1001 69 16
1001 70 16
1001 71 16
1001 72 16
1001 73 14
1001 74 14
1001 75 14
1001 76 14
1001 77 14
1001 78 14
1001 79 14
1001 80 14
1001 81 14
1001 82 14
1001 83 14
1001 84 14
1002 85 17
1002 86 17
1002 87 17
1002 88 17
1002 89 15
1002 90 15
1003 91 18
1003 92 18
1003 93 18
1003 94 18
1003 95 18
1003 96 18
1004 97 19
1004 98 19
1004 99 19
但不知何故,我仍然得到我试图更改的旧数据。任何帮助将不胜感激。谢谢
除了最后一个条目似乎与您的逻辑不一致外,以下代码应该可以满足您的需求:
1004 99 19
结果是:
1004 99 20
根据你的逻辑。
proc sort data=have;
by ID day;
run;
data want;
merge have have (firstobs=2 rename=(id=id2 day=day2 temp=temp2));
output;
if (day2 > day) then do;
do while (day < day2 - 1);
day + 1; output;
end;
end;
keep id day temp;
run;
一个稳健的解决方案将在每个 id
组的开始重置迭代。您的示例数据不显示连续组的开始日期早于前一组的情况。如果不测试 id 组的开始(或在组内),结果可能与预期不同。
示例 1:1 与从 obs=2
开始的第二个自我合并,以提供来自 next 的 lead 值排。数据已用组 id=1007
和 id=1009
进行了修改,因此需要 重置 。组within-ness条件用id=lead_id
data have; input
ID day temp; datalines;
1001 68 16
1001 73 14
1002 85 17
1002 89 15
1003 91 18
1004 97 19
1004 99 20
1004 106 12
1005 109 15
1006 111 18
1006 115 19
1006 120 20
1006 122 21
1007 1 1
1007 15 0
1007 16 2
1007 20 5
1008 35 12
1008 37 14
1008 45 20
run;
data want (drop=lead:);
merge have have(keep=day id rename=(id=lead_id day=lead_day) firstobs=2);
* by is not used for a 1:1 merge;
if id=lag(id) and day < lag(day) then do;
put "ERR" "OR: Stopping because days are not ordered within " ID= "at " day= ;
stop;
end;
if (id=lead_id) then do day=day to lead_day-1;
output; * fill-in rows with same temp;
end;
else
output; * final row of group;
run;