If statement SAS错误:SUM的Null参数无效

If statement SAS错误:SUM的Null参数无效,if-statement,sas,sas-macro,datastep,If Statement,Sas,Sas Macro,Datastep,因此,我有一个名为table1的数据,如下所示: Obs ID M_201812 M_201901 M_201902 M_201903 1 X1 1 . . . 2 X2 1 1 . . 3 X3 . 1 1 . 4 X4 .

因此,我有一个名为table1的数据,如下所示:

Obs  ID  M_201812  M_201901      M_201902    M_201903

1    X1     1         .             .           . 
2    X2     1         1             .           . 
3    X3     .         1             1           . 
4    X4     .         1             .           . 
5    X5     .         1             .           . 
6    X6     1         .             .           . 
7    X7     1         1             .           . 
8    X8     1         1             .           . 
9    X9     .         .             1           . 
10   X10    1         1             .           . 
M_201812,M_201901,M_201902,M_201903
这里的每一列都是一个月,它是根据以前运行的一些宏动态生成的。月份将是动态的,并且会有所不同。我需要做的是计算过去3个月、6个月和12个月的总和。我的想法是: A将列名存储在宏变量中:

proc sql noprint;
    select distinct name
    into :cols2 separated by ','  
    from dictionary.columns
    where upcase(memname) = 'Table1' and name not in ('ID');
    ;
quit;
%put &cols2.
data table1;
set table1;

if count("&cols2",",") <=3 then do;
3m_total=sum(of &cols2);
6m_total=sum(of &cols2);
12m_total=sum(of &cols2);
end;
else if 3< count("&cols2",",") <=6 then do;
3m_total=sum(%scan(%superQ(cols2),-1,%str(,)),%scan(%superQ(cols2),-2,%str(,)),%scan(%superQ(cols2),-3,%str(,)));
6m_total=sum(of &cols2);
12m_total=sum(of &cols2);
end;
else if 6< count("&cols2",",") <=12 then do;
3m_total=sum(%scan(%superQ(cols2),-1,%str(,)),%scan(%superQ(cols2),-2,%str(,)),%scan(%superQ(cols2),-3,%str(,)));
6m_total=sum(%scan(%superQ(cols2),-1,%str(,)),%scan(%superQ(cols2),-2,%str(,)),%scan(%superQ(cols2),-3,%str(,)),%scan(%superQ(cols2),-4,%str(,)),%scan(%superQ(cols2),-5,%str(,)),%scan(%superQ(cols2),-6,%str(,)));
12m_total=sum(of &cols2);
else do;
    3m_total=sum(%scan(%superQ(cols2),-1,%str(,)),%scan(%superQ(cols2),-2,%str(,)),%scan(%superQ(cols2),-3,%str(,)));
    6m_total=sum(%scan(%superQ(cols2),-1,%str(,)),%scan(%superQ(cols2),-2,%str(,)),%scan(%superQ(cols2),-3,%str(,)),%scan(%superQ(cols2),-4,%str(,)),%scan(%superQ(cols2),-5,%str(,)),%scan(%superQ(cols2),-6,%str(,)));
    12m_total=sum(%scan(%superQ(cols2),-1,%str(,)),%scan(%superQ(cols2),-2,%str(,)),%scan(%superQ(cols2),-3,%str(,)),%scan(%superQ(cols2),-4,%str(,)),%scan(%superQ(cols2),-5,%str(,)),%scan(%superQ(cols2),-6,%str(,)),
    %scan(%superQ(cols2),-7,%str(,)),%scan(%superQ(cols2),-8,%str(,)),%scan(%superQ(cols2),-9,%str(,)),%scan(%superQ(cols2),-10,%str(,)),%scan(%superQ(cols2),-11,%str(,)),%scan(%superQ(cols2),-12,%str(,)));
    end;
    run;
产出如下:

Obs  ID  M_201812  M_201901      M_201902    M_201903

1    X1     1         .             .           . 
2    X2     1         1             .           . 
3    X3     .         1             1           . 
4    X4     .         1             .           . 
5    X5     .         1             .           . 
6    X6     1         .             .           . 
7    X7     1         1             .           . 
8    X8     1         1             .           . 
9    X9     .         .             1           . 
10   X10    1         1             .           . 
M_201812,M_201901,M_201902,M_201903
B根据变量中的项目数创建金额:

proc sql noprint;
    select distinct name
    into :cols2 separated by ','  
    from dictionary.columns
    where upcase(memname) = 'Table1' and name not in ('ID');
    ;
quit;
%put &cols2.
data table1;
set table1;

if count("&cols2",",") <=3 then do;
3m_total=sum(of &cols2);
6m_total=sum(of &cols2);
12m_total=sum(of &cols2);
end;
else if 3< count("&cols2",",") <=6 then do;
3m_total=sum(%scan(%superQ(cols2),-1,%str(,)),%scan(%superQ(cols2),-2,%str(,)),%scan(%superQ(cols2),-3,%str(,)));
6m_total=sum(of &cols2);
12m_total=sum(of &cols2);
end;
else if 6< count("&cols2",",") <=12 then do;
3m_total=sum(%scan(%superQ(cols2),-1,%str(,)),%scan(%superQ(cols2),-2,%str(,)),%scan(%superQ(cols2),-3,%str(,)));
6m_total=sum(%scan(%superQ(cols2),-1,%str(,)),%scan(%superQ(cols2),-2,%str(,)),%scan(%superQ(cols2),-3,%str(,)),%scan(%superQ(cols2),-4,%str(,)),%scan(%superQ(cols2),-5,%str(,)),%scan(%superQ(cols2),-6,%str(,)));
12m_total=sum(of &cols2);
else do;
    3m_total=sum(%scan(%superQ(cols2),-1,%str(,)),%scan(%superQ(cols2),-2,%str(,)),%scan(%superQ(cols2),-3,%str(,)));
    6m_total=sum(%scan(%superQ(cols2),-1,%str(,)),%scan(%superQ(cols2),-2,%str(,)),%scan(%superQ(cols2),-3,%str(,)),%scan(%superQ(cols2),-4,%str(,)),%scan(%superQ(cols2),-5,%str(,)),%scan(%superQ(cols2),-6,%str(,)));
    12m_total=sum(%scan(%superQ(cols2),-1,%str(,)),%scan(%superQ(cols2),-2,%str(,)),%scan(%superQ(cols2),-3,%str(,)),%scan(%superQ(cols2),-4,%str(,)),%scan(%superQ(cols2),-5,%str(,)),%scan(%superQ(cols2),-6,%str(,)),
    %scan(%superQ(cols2),-7,%str(,)),%scan(%superQ(cols2),-8,%str(,)),%scan(%superQ(cols2),-9,%str(,)),%scan(%superQ(cols2),-10,%str(,)),%scan(%superQ(cols2),-11,%str(,)),%scan(%superQ(cols2),-12,%str(,)));
    end;
    run;

这发生在最后一个else do语句中。我一辈子都不明白为什么sas不能阅读一个简单的if-then-do-else语句。if条件或调用宏变量时是否有错误?这里的任何帮助都将不胜感激。非常感谢。

如果看不到宏逻辑实际生成的代码,很难判断。 但很可能是因为生成的两个逗号之间没有逗号,如下所示:

475   data test;
476     y=sum(1,,2,3);
                -
                159
ERROR 159-185: Null parameters for SUM are invalid.

477   run;
您需要要么不生成额外的逗号,要么在逗号之间加上一些东西。因此,要么是缺少值的句点,要么是0

通常,如果不使用逗号,SAS会更容易。因此,获取一个以空格分隔的变量名列表

proc contents data=Table1 noprint
  out=_contents (where=(name ne 'ID'))
; 
run;

proc sql noprint;
select name
     , case when (varnum>9) then name else ' ' end 
     , case when (varnum>6) then name else ' ' end 
     , case when (varnum>3) then name else ' ' end
  into :cols_12 separated by ' '
     , :cols_3 separated by ' '
     , :cols_6 separated by ' '
     , :cols_9 separated by ' '
  from _contents
  order by name
;
quit;
然后使用of关键字使用名称列表,这样它们之间就不需要逗号了

data want;
  set table1;
  total_3m=sum(0,of &cols_3);
  total_6m=sum(0,of &cols_6);
  total_9m=sum(0,of &cols_9);
  total=sum(0,of &cols_12);
run;

还要记住为变量使用有效的名称。变量名不能以数字开头。

请考虑将数据从宽改为长,然后对3/6/12个月的运行总和运行多个相关的聚合SQL子查询。这将达到您提到的预期结果:

我需要做的是计算过去3个月、6个月和12个月的总和

资料

重塑

聚集

proc-sql; 创建表Run_Sums作为 选择m.ID, m、 月日, m、 价值观, 选择总和值 从月份\u数据\u长sub 其中sub.ID=m.ID 和次月日>=intnx'Month',m.Month\u Date,-3 子月日=intnx'Month',m.Month\u Date,-6 子月日=intnx'Month',m.Month\u Date,-12
你为什么要从这个结构开始呢?你不能从垂直结构开始,其中日期是变量的值,而不是变量的名称吗?重复@Tom,这是一个报告结构,不是一个维护或计算数据的好结构。这是可以做到的,但却是一件痛苦的事情。具体地说,回显@Reeza时,您应该使用MM/YYY列保持数据的长度,而不是宽度,这对几乎任何分析都有很大帮助。见proc转置。谢谢汤姆的建议。我运行了你的代码。但也有一些例子,我注意到一些ID错误地填充了总共300万、600万、1200万个ID。例如:对于给定表格中的ID X8,他的3m总数应该是1从201901到201903,他的6个月总数应该是2从任何可用到201903。但碰巧我得到了1,总共3米和6米。如果有解决办法,一定要告诉我。如果变量未按时间顺序定义,则如何选择哪些变量不起作用的逻辑。查看宏变量和_内容数据集的值以了解发生了什么。也许可以将keep=M_20:datastep选项添加到proc内容的输入中,以仅列出与您的模式匹配的变量。但是对于一个更健壮的解决方案,你真的应该将日期保存在数据中,而不是变量名中,这样逻辑就容易多了。谢谢Tom,我将尝试编辑它。最后一个问题。在一个基本的数据步骤中,如果我运行的扫描函数超出了字符串的长度范围,是否有办法终止该进程?假设我有一个单词编码,我运行Scancoding,10-它将是空的。但我不想让它执行任何事情。可能?有关扫描和%SCAN的问题在某些方面完全不同。在普通SAS代码中,您可以测试扫描是否只返回空格并采取一些操作。但在您的示例中,您使用%SCAN生成SAS代码,然后将对其进行编译。如果希望根据%SCAN返回的结果有条件地生成不同的代码,则需要宏逻辑,这通常意味着实际的宏。虽然使用%sysfuncifc。。。。在某些情况下可以在开放代码中使用。谢谢冻糕!我试试看。