sas - PROC FORMAT 可以用于跨多列的组内求和吗?
问题描述
我有一个约 9 亿行的数据集,每一行代表给定患者在 3 年内的索赔,每个索赔有多达 25 个诊断代码排列为变量,以及一个转换特定子集的键将代码转换为“慢性病”。
像这样:
data claims;
infile cards;
input id $ type dg1 $ dg2 $ dg3 $ dg4 $ [...] dg25 $;
cards;
A 40 A123 A234 B345 . [...] .
A 10 A234 . . . . [...] .
B 40 C567 1234 Z4657 [...] .
B 40 C567 1233 X4787 [...] .
;
run;
data chrons;
infile cards;
input chron nm $ code $ ;
cards;
1 ckd A234
1 ckd C567
1 ckd 1233
2 copd B345
2 copd C233
3 diab A234
3 diab 1234
[...]
55 foo Z4657
55 foo X4787
;
run;
为了确定条件是否为“慢性”,我必须计算出现条件的索赔数量(在任何 DG 中),不同条件的最低索赔数量不同。
目前我已经使用一个非常笨重的数据步骤完成了这项工作,看起来或多或少像这样:
/* first a SQL loop that puts the codes into macros: */
%macro chron(start,end);
proc sql noprint;
%do k=&start. %to &end.;
select strip(catt("'",code,"'"))
into :chron&k. separated by ','
where chron=&k.
from chrons;
%end;
quit;
%mend;
%chron(1,55);
/* then a double loop array for each of the 55 conditions in any of the 25 vars */
data claims_1yr;
set claims;
array dgc(25) dg1-dg25;
array cond(55) cond1-cond55;
do i=1 to 55;
do j=1 to 25;
if cond(i) < 1 then do;
if dgc(j) in (&&chron&i.) then cond&i.=1; else cond&i.=0;
end;
end;
run;
随后是一些 SQL 总和,按索赔数量和基于索赔类型的进一步条件等。一些条件有特殊情况,比如有一个代码列表,如果出现在任何 dg{n} 变量中,则索赔不计入,或要求代码位于前 2 个 dg{n} 空格内。
我想知道是否有一种更简单的方法可以使用 PROC FORMAT(我不是特别熟悉)和 PROC MEANS 或 PROC Summary 来获取摘要数据集,其中每个 ID 都有每个 ID 的索赔数量条件(无论代码在哪个 dg 中)。就计算而言,循环的数量是残酷的;我上次运行它时,花了将近 48 小时才完成。
一位同事建议:
%macro sl(st,end);
proc sql;
%do l=&st. %to &end.;
create table claims_&l as
select distinct id,
sum(case when (dg1 in (&&chron&l.) or
dg2 in (&&chron&l.) or
dg3 in (&&chron&l.) or
dg4 in (&&chron&l.) [...] or
dg25 in (&&chron&l.) then 1 else 0 end) as chron&l.
from claims group by id;
%end;
quit;
%mend;
%sl(1,55);
但这通常会在大约一个小时后导致段错误。
datastep 并不是世界上最糟糕的事情,但我想知道这个谜题是否对任何人来说都很熟悉,或者是否有一个我忽略的明显答案(遗憾的是,不能选择使用 SAS 9.3 以外的任何东西)。
最后的目标是拥有一个如下所示的数据集:
ID Cond Claims
A diab 2
A copd 1
A ckd 2
B diab 1
B ckd 2
B foo 2
或者
ID cond1 cond2 cond3 [...] cond55
A 2 1 2 [...] 0
B 2 0 1 [...] 2
nb 平均患者在档案中有约 70 项索赔(有约 1300 万不同的患者)。之前的运行表明,其中约 40% 的人至少患有一种慢性病,其中一半(总数的 20%)患有不止一种慢性病。实际上“拥有”条件是基于在给定时间段内具有相关代码的最小索赔数量(不同条件的不同最小值)。
谢谢!
解决方案
这在数组中使用“值”并创建 CONDn 变量并按 ID 计数。
data claims;
infile cards missover;
input id $ type (dg1-dg5)($);
cards;
A 40 A123 A234 B345
A 10 A234
B 40 C567 1234 Z4657
B 40 C567 1233 X4787
;;;;
run;
data chrons;
infile cards;
input chron nm $ code $;
cards;
1 ckd A234
1 ckd C567
1 ckd 1233
2 copd B345
2 copd C233
3 diab A234
3 diab 1234
;;;;
run;
filename FT77F001 temp;
data _null_;
file FT77F001;
set chrons;
by chron nm;
if first.chron then put +3 'Cond' chron '=' @;
put code :$quote. 'in DG' @;
if not last.chron then put ' or ' @;
if last.chron then do;
put ';' +3 'label Cond' chron '=' nm:$quote. ';';
end;
run;
data want1(keep=id cond:) / view=want1;
set claims;
array DG[*] dg:;
%inc FT77F001 / source2;
run;
proc summary data=want1 nway;
class id;
output out=want2(drop=_type_) sum(cond:)=;
run;
proc print;
run;
推荐阅读
- java - 如何从服务器获取 CasToken?
- javascript - 如何在 TypeScript / JavaScript 中缩写驼峰式文本字符串
- angular - 如何有条件地允许导航到用户
- javascript - Jquery 动画滑块
- python - 为什么 Django 开发人员使用 Django 内置管理面板?是否说必须使用而不是 html 主题?
- node.js - 如何在 JSON 中表示元数据
- sql-server - PERFORMANCE - 按 SELECT UNION 中的特定查询块过滤
- android - Android Kotlin - Webview 数据库
- java - 我如何从数据库中选择一个特定的值
- sharepoint - 使用powerapps将元素从列表移动到共享点中的另一个列表