使用 UPDATE 折叠观察时如何保留不在 BY 组中的变量的原始值
How to retain original value of variable not in BY group when using UPDATE to collapse observations
我有一份在特定日期进行医疗访问的人员名单,并且我已经将他们标记为进行特定诊断。现在我试图折叠这些标志以创建一个文件,每行有一个 person/one 日期。我找到了一个部分有效的解决方案,使用 UPDATE(在此处找到:SAS collapse dates)。然而,这会用某个人在特定日期的最后诊断代码覆盖标记的诊断代码。这是我的数据的简化版本:
data have;
input id id_date diag_code $ flag;
datalines;
1 1 a .
1 1 b 1
1 1 c .
1 2 d 1
1 2 e .
1 2 f 1
2 1 g .
2 1 h .
2 1 i 1
2 2 j 1
3 1 k .
;
run;
data want;
update have (obs=0) have;
by id id_date;
run;
输出:
diag_
Obs id id_date code flag
1 1 1 c 1
2 1 2 f 1
3 2 1 i 1
4 2 2 j 1
5 3 1 k .
我想得到的是:
diag_
Obs id id_date code flag
1 1 1 b 1
2 1 2 d 1
3 2 1 i 1
4 2 2 j 1
5 3 1 k .
所以基本上,我想保留 diag_code 来自具有标志 = 1 的第一个观察结果。我已经尝试使用 RENAME 选项来防止覆盖变量,但是由于 UPDATE 首先读取具有 0 个观察值的数据集,(新的)原始变量出现但为空:
data want;
update have (obs=0 rename=(diag_code=orig_diag_code)) have;
by id id_date;
run;
orig_
diag_ diag_
Obs id id_date code flag code
1 1 1 1 c
2 1 2 1 f
3 2 1 1 i
4 2 2 1 j
5 3 1 . k
有什么想法吗?
编辑:
添加 where flag = 1 仍然错误地显示出现多个标志时的最后诊断,并且不会在标志丢失时产生日期观察:
data want;
update have (obs=0) have;
by id id_date;
where flag=1;
run;
diag_
Obs id id_date code flag
1 1 1 b 1
2 1 2 f 1
3 2 1 i 1
4 2 2 j 1
您需要将 DIAG_CODE 变量移开,这样它就不会被 UPDATE 语句更新。您需要创建一个新变量来保留在第一个 FLAG=1 记录中找到的值。然后re-assign右值返回DIAG_CODE.
data want;
update have (obs=0) have(rename=(diag_code=diag_code_orig));
by id id_date;
if 0 then keep_diag=diag_code ;
retain keep_diag ;
if first.id_date then call missing(keep_diag);
if flag=1 then keep_diag=coalescec(keep_diag,diag_code_orig);
diag_code=coalescec(keep_diag,diag_code_orig);
drop keep_diag diag_code_orig;
run;
您可以改为 re-merge 第二步中第一个 FLAG=1 记录的 DIAG_CODE 值。
data want ;
update have(obs=0) have;
by id id_date;
run;
data want ;
merge want
have(keep=id id_date diag_code flag rename=(flag=xflag)
where=(xflag=1 and not missing(diag_code)))
;
by id id_date;
if first.id_date;
drop xflag;
run;
可以使用标志(或状态维护)变量选择满足某些条件的组中的第一行。
这里有两种方法:
- DOW 遍历组,不需要
retain
或first.
- 只有
retain
、first.
和 last.
的隐式循环
代码:
* DOW over group with last., no retain or first.;
data want;
do _n_ = 1 by 1 until (last.id_date);
set have;
by id id_date;
if flag and not flagged then do;
output;
flagged = _n_;
end;
end;
if not flagged then output;
drop flagged;
run;
* Only implicit loop with retain, first. and last.;
data want;
retain flagged;
drop flagged;
set have;
by id id_date;
if first.id_date then flagged = .;
if flag and not flagged then do;
flagged = 1;
output;
end;
if last.id_date and not flagged then
output;
run;
我有一份在特定日期进行医疗访问的人员名单,并且我已经将他们标记为进行特定诊断。现在我试图折叠这些标志以创建一个文件,每行有一个 person/one 日期。我找到了一个部分有效的解决方案,使用 UPDATE(在此处找到:SAS collapse dates)。然而,这会用某个人在特定日期的最后诊断代码覆盖标记的诊断代码。这是我的数据的简化版本:
data have;
input id id_date diag_code $ flag;
datalines;
1 1 a .
1 1 b 1
1 1 c .
1 2 d 1
1 2 e .
1 2 f 1
2 1 g .
2 1 h .
2 1 i 1
2 2 j 1
3 1 k .
;
run;
data want;
update have (obs=0) have;
by id id_date;
run;
输出:
diag_
Obs id id_date code flag
1 1 1 c 1
2 1 2 f 1
3 2 1 i 1
4 2 2 j 1
5 3 1 k .
我想得到的是:
diag_
Obs id id_date code flag
1 1 1 b 1
2 1 2 d 1
3 2 1 i 1
4 2 2 j 1
5 3 1 k .
所以基本上,我想保留 diag_code 来自具有标志 = 1 的第一个观察结果。我已经尝试使用 RENAME 选项来防止覆盖变量,但是由于 UPDATE 首先读取具有 0 个观察值的数据集,(新的)原始变量出现但为空:
data want;
update have (obs=0 rename=(diag_code=orig_diag_code)) have;
by id id_date;
run;
orig_
diag_ diag_
Obs id id_date code flag code
1 1 1 1 c
2 1 2 1 f
3 2 1 1 i
4 2 2 1 j
5 3 1 . k
有什么想法吗?
编辑: 添加 where flag = 1 仍然错误地显示出现多个标志时的最后诊断,并且不会在标志丢失时产生日期观察:
data want;
update have (obs=0) have;
by id id_date;
where flag=1;
run;
diag_
Obs id id_date code flag
1 1 1 b 1
2 1 2 f 1
3 2 1 i 1
4 2 2 j 1
您需要将 DIAG_CODE 变量移开,这样它就不会被 UPDATE 语句更新。您需要创建一个新变量来保留在第一个 FLAG=1 记录中找到的值。然后re-assign右值返回DIAG_CODE.
data want;
update have (obs=0) have(rename=(diag_code=diag_code_orig));
by id id_date;
if 0 then keep_diag=diag_code ;
retain keep_diag ;
if first.id_date then call missing(keep_diag);
if flag=1 then keep_diag=coalescec(keep_diag,diag_code_orig);
diag_code=coalescec(keep_diag,diag_code_orig);
drop keep_diag diag_code_orig;
run;
您可以改为 re-merge 第二步中第一个 FLAG=1 记录的 DIAG_CODE 值。
data want ;
update have(obs=0) have;
by id id_date;
run;
data want ;
merge want
have(keep=id id_date diag_code flag rename=(flag=xflag)
where=(xflag=1 and not missing(diag_code)))
;
by id id_date;
if first.id_date;
drop xflag;
run;
可以使用标志(或状态维护)变量选择满足某些条件的组中的第一行。
这里有两种方法:
- DOW 遍历组,不需要
retain
或first.
- 只有
retain
、first.
和last.
的隐式循环
代码:
* DOW over group with last., no retain or first.;
data want;
do _n_ = 1 by 1 until (last.id_date);
set have;
by id id_date;
if flag and not flagged then do;
output;
flagged = _n_;
end;
end;
if not flagged then output;
drop flagged;
run;
* Only implicit loop with retain, first. and last.;
data want;
retain flagged;
drop flagged;
set have;
by id id_date;
if first.id_date then flagged = .;
if flag and not flagged then do;
flagged = 1;
output;
end;
if last.id_date and not flagged then
output;
run;