Sas 可以使用PROC格式在多个列的组内求和吗?

Sas 可以使用PROC格式在多个列的组内求和吗?,sas,bigdata,Sas,Bigdata,我有一个约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

我有一个约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; 
但这通常会在大约一小时后导致SEG故障

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

n、 b。 平均每位患者在档案中有约70项索赔(约1300万名不同的患者)。之前的研究表明,其中大约40%的人至少有一种慢性病,其中一半(占总数的20%)有一种以上的慢性病。实际上,“拥有”条件是基于给定时间段内具有相关代码的索赔的最小数量(不同条件下的不同最小值)


谢谢

我的方法是使用datastep将数据集转换为每个诊断代码的一行,将慢性病格式应用于该列。然后,
PROC tablate
可能是您获得每个ID的每个条件的诊断计数的最佳选择。初始转置不会很快,但它将使用数据步骤,因此即使是一个大文件,它也可以工作,并且不会花费数小时,除非您的磁盘速度太慢。只需确保您的输出数据集只过滤到您需要的三个左右的变量-ID、diag.code、type,我想

您可以使用PROC格式上的CNTLIN功能导入慢性病。您至少需要:

  • 开始=格式输入(即诊断代码)
  • 标签=格式输出(即慢性病)
  • FMTNAME=您想命名的名称,字符为$
  • 类型='c'(字符)
  • 包含HLO='o'和空标签的单行或任何不匹配的行应折叠为('其他'不匹配格式)

然后
proc format cntlin=[formatdataset];运行
将导入它。

这将在数组中使用“value”并创建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;


将所需诊断频率表的内存需求视为哈希表

9亿次索赔,平均每位患者70次索赔,意味着约有1300万名不同的患者

假设每个病人平均有10种慢性病。因此,您的目标(ID、条件、频率)的垂直数据布局形式中有130M行

进一步假设内存中的散列对象键+每行需要75字节的数据。因此,包含完整的所需垂直表单结果的哈希可能需要>=~9G RAM

因此,您可以在一次数据传递中执行诊断->条件映射和计算频率

通过基于的评估中的
映射为慢性病控制表生成的代码(per@data null)可能是最快的解决方案之一。生成的代码可能会进一步优化——我的理解是,SAS数据步骤代码中的求值是一个完整的路径求值,这意味着每个子句都已完成。比如说

<condition-1> = (clause-1) OR (clause-2) … OR … (clause-k);
<condition-2> = (clause-1) OR (clause-m) … OR … (clause-n);

根据
data\u null\u
的回答,(子句-k)将是
(“在DG中)

这是部分代码,您可以发布您尝试的实际代码吗,例如,所有代码都缺少From语句。那就是9000亿条记录,你要总结的每条记录有25条?您将在communities.sas.com上获得更好的解决方案,因为这是一个效率类型的问题,而不是一般性的问题。您使用Chron的数据集做什么?我很好奇是否有使用PROC格式的解决方案,因此这里的问题就来了。我想我也会转到SAS。chron数据集是用于获取每个条件的代码列表的人行横道;我已经澄清了在复制.Proc格式时遗漏这些行的SQL代码,但我怀疑临时数组也可以。你对我剩下的问题有答案吗?啊,我编辑是为了澄清--这是9亿行,不是10亿行--你想让我发布省略号省略的代码吗?我修正了陈述中的错误;当我转录时,它们被遗漏了。谢谢——我已经能够cntlin chrons数据集,但是转置会产生约200亿行的表,在我必须这样做的环境中,空间不是很容易获得(需要对其中4个数据集进行此操作,所有数据集都是60-90gb)。空间的限制是我希望以一种更优雅的方式来做这件事的原因之一(似乎格式和2d数组可以用proc means或proc TABLATE来做,但是无论我是在做pipedreaming还是那里有一个“there”,我都很难理解)。你能把它作为一个视图来创建吗?这将把信息一行一行地导入PROC TABLATE中。文本数据将写入临时文件,我认为它将进入工作库,在会话结束时将消失。@Reeza是的,“墙纸”文件是临时的。你认为它应该是永久的吗?我不知道你可以通过这种方式引用数组的所有元素,非常酷。假设SAS只是在每个“DG”中执行一个“do over”循环——这在功能上与我现在的数据步骤中的双循环不同吗?@BenLerner我不知道它在引擎盖下是如何工作的。另一个问题
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;
<condition-1> = (clause-1) OR (clause-2) … OR … (clause-k);
<condition-2> = (clause-1) OR (clause-m) … OR … (clause-n);
select 
  when (clause-1) do; condition1=1; end;
  when (clause-2) do; condition2=1; condition14=1; end; /* a non-distinct mapping in the control data */
  …
  when (clause-k) do; condition<p> = 1; end;
  otherwise condition_healthy = 1;
end;