【问题标题】:Cumulative sum of columns in SASSAS中列的累积和
【发布时间】:2018-04-09 01:10:34
【问题描述】:

我正在尝试对变量求和

N1 N2 N3
1  1  1
1  .  1
1  1  .

想要

N1 N2 N3 B1 B2 B3
1  1  1  1  2  3
1  .  1  1  1  2
1  1  .  1  2  2

我正在尝试的数组看起来根本不起作用..

data temp2; 
    set temp; 
    array hh(*) N:; 
    array bb(3); 
    do i=1 to dim(hh);
        bb(i)=bb(i)+hh(i+1);
    end; 
run;

我不想使用转置和累积总和。

【问题讨论】:

    标签: sas


    【解决方案1】:

    首先,您的算法有错误:累积值

    • 不应从自身计算下一个输入值,
    • 但来自先前的累积值和相应的输入值。

    你宁愿需要bb(i) = bb(i-1) + hh(i)。当然,这在i 为1 时是行不通的,因为没有hh(0),所以你从i = 2 开始这样做。

    其次,您需要处理缺失值,类似于 SQL 中的 coalesce。让我们为此使用ifn,这是一个返回数值变量的函数。第一个参数是条件,第二个是条件为真时的返回值,第三个是条件为假时的返回值。

    把它们放在一起;

    data AFTER;
        set TEMP;
        array hh(*) N:; 
        array bb(3); 
    
        bb1 = ifn(missing(N1), 0, N1);
        do i=2 to 3;
            bb(i) = bb(i-1) + ifn(missing(hh(i)), 0, hh(i));
        end; 
    
        drop i;
    run; 
    

    这个解决方案的缺点array bb(3)do i=2 to 3中的硬编码3,用户3658367试图用dim(hh)解决这个问题。不幸的是,这只适用于其中一个。

    这样更好;

    proc sql; 
        select count(*) 
          into :B_count 
          from sasHelp.vColumn 
         where libname eq 'WORK'
           and memName eq 'TEMP'
           and name like 'N%';
    quit;
    
    data AFTER;
        set TEMP;
        array hh(*) N:; 
        array bb(&B_count); 
    
        bb1 = ifn(missing(N1), 0, N1);
        do i=2 to &B_count;
            bb(i) = bb(i-1) + ifn(missing(hh(i)), 0, hh(i));
        end; 
    
        drop i;
    run; 
    

    我添加了条件name like 'N%',因为我假设在您的实际问题中,TEMP 有其他变量,而不是您累积的变量。

    关于下面的 cmets :如果你从一开始就没有参与这个帖子,你可以忽略它们。我将它们包含在上面的文本中。

    (致这些 cmets 的作者:感谢您的意见。)

    【讨论】:

    • 这只能工作一半。当有缺失值时它会停在那里并且不携带该值。所以输出变为 N1 N2 N3 B1 B2 B3 1 1 1 1 2 3 1 。 1 1 1 1 。 1 2
    • array bb(3); 没有定义 临时 变量。它定义了名为BB1BB3 的常规变量。如果之前没有定义它们,那么它们将是数字的。如果它们已经在步骤中定义,那么它们需要具有一致的类型。要制作临时变量,您需要将 _temporary_ 关键字添加到 array 语句中。
    • 为什么将8.格式附加到变量B1-B3?
    • 感谢您的评论,我会在这个周末整合它们并测试代码。
    • 更改 bb(i) = bb(i-1) + hh(i) 以使用 SUM() 函数处理缺失值。
    【解决方案2】:

    我对数组不太满意,所以我会使用宏来完成这项工作。

    data temp;
    input N1 N2 N3;
    datalines;
    1 1 1
    1 . 1
    1 1 .
    ;
    run;
    
    options mprint mlogic;
    
    proc sql;
    select name into:cols separated by ','
    from dictionary.columns
    where libname = upcase("work") and memname = upcase("temp") and upcase(name) like 'N%';
    quit;
    
    %macro cumul_colsum;
    
    data temp2;
    set temp;
    run;
    
    %do i = 1 %to %sysfunc(countw(%superq(cols)));
    
    %let var = %scan(%superq(cols),&i,%str(,)); %put |&var|;
    
    data temp2;
    set temp2;
    B&i. = sum(of N1-&var.);
    run;
    
    %end;
    %mend cumul_colsum; %cumul_colsum;
    

    并获得所需的结果,在这种情况下,这是 OP 需要的。我使用了与 Dirk 相同的 like 'N%' 将列名提供给宏,并使用 do 循环来创建具有累积总和的列。对于庞大的数据集,这可能需要一段时间。但更容易理解 (options mprint nonotes;) 发生了什么。

    【讨论】:

      【解决方案3】:

      遵循@Reeza 的建议,使用 sum 而不是 + 来处理缺失值。如下所示。

      data have;
      input
      N1 N2 N3;
      datalines;
      1  1  1
      1  .  1
      1  1  .
      ;
      
      data temp2; 
      set have; 
      array hh(*) N1 N2 N3; 
      
      array bb(3) b1 b2 B3; 
      do i= 1 to dim(hh);
      if i= 1 then bb(i) = hh(i);
       else   bb(i)= sum(bb(i-1),hh(i));
      end; 
      drop i;
      

      运行;

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-01-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多