【问题标题】:SAS, sum by groupSAS,按组求和
【发布时间】:2018-04-26 18:51:16
【问题描述】:

我想通过 var1 计算总和。你能用两种方法来计算吗? SQL 和数据步与 if first.var1。

data have;
input var1 var2$ var3;
datalines;

1 a 3
1 a 4
1 a 3
2 b 5
2 b 3
3 c 1
;
run;

data want;
input var1 var2 $ var3 sum_by_var1;
datalines;

1 a 3 10
1 a 4 10
1 a 3 10
2 b 5 9
2 b 3 9
3 c 1 9
;
run;

我的两种方式:

下面的代码适用于这个小数据集,但我想知道它是否适用于大数据集,因为很难检查结果。

proc sql;
 create table new as 
 select 
 *
 ,sum(var3) as sum_by_var1
 from have
 group by var1
 order by var1
 ;
run;

下面的代码不起作用

data new2;   
   set have;       
   by var1; 
   if first.var1 then
   by_var1 + var3;
run;

【问题讨论】:

  • 请提供您迄今为止为解决此问题所做的任何尝试。除了数据步骤或 SQL 之外,还应考虑 PROC MEANS/SUMMARY/UNIVARIATE,因为它们旨在有效地汇总数据。
  • 我更新了我的“解决方案”
  • 你的方法是正确的,是常用的一种方式,另一种是通过merge。在此处查看此示例:github.com/statgeek/SAS-Tutorials/blob/master/…
  • 如果你有非常大的数据——你需要先排序,这是密集的——你可能想要一个 DoW 循环解决方案,而不是通过数据步骤,但那是更多的代码。除非您有数千万条记录,否则 SQL 或 PROC MEANS 解决方案应该足以满足 IMO 的需求。

标签: sas


【解决方案1】:

要使用您需要使用的数据步骤来修复您的计算:

  1. Retain关键字通过var1计算总和,
  2. Output 关键字只输出一次 var1 的总和计算;那是到达 var1 的最后一次观察时,
  3. 如果您想要分离的数据,您必须重新加入您的 Have 表。

修复:

data new2;   
   set have;       
   by var1; 
   retain sum_by_var1;
   if first.var1 then do; sum_by_var1=0; end;
   sum_by_var1 + var3;
   if last.var1 then do; output; end;
run;

输出:

var1=1 var2=a var3=3 sum_by_var1=10 
var1=2 var2=b var3=3 sum_by_var1=8 
var1=3 var2=c var3=1 sum_by_var1=1 

【讨论】:

    【解决方案2】:

    这里有两个完整的示例,说明如何使用分组变量执行此操作。一种方法使用 SQL,第二种方法使用 PROC MEANS。 在这个例子中,我正在做一个平均,但你可以用 SUM 代替这个词来得到你想要的结果。

    ******************************************************;
    *Add average value to a dataset;
    *Solution 1 - PROC MEANS + Data step;
    ******************************************************;
    
    proc means data=sashelp.class noprint;
        output out=avg_values mean(height)=avg_height;
    run;
    
    data class_data;
        set sashelp.class;
    
        if _n_=1 then
            set avg_values;
    run;
    
    proc print data=class;
    run;
    
    *Solution 2 - PROC SQL - note the warning in the log;
    PROC SQL;
    Create table class_sql as
    select *, mean(height) as avg_height
    from sashelp.class;
    quit;
    
    ******************************************************;
    *Add average value to a dataset - with grouping variables;
    *Solution 1 - PROC MEANS + Data step;
    ******************************************************;
    proc means data=sashelp.class noprint nway;
    class sex;
        output out=avg_values mean(height)=avg_height;
    run;
    
    *sort data before merge;
    proc sort data=sashelp.class out=class;
    by sex;
    run;
    
    data class_data;
     merge class avg_values;
     by sex;
    
    
    run;
    
    proc print data=class_data;
    run;
    
    *Solution 2 - PROC SQL - note the warning in the log;
    PROC SQL;
    Create table class_sql as
    select *, mean(height) as avg_height
    from sashelp.class
    group by sex;
    quit;
    

    【讨论】:

      【解决方案3】:

      当使用和运算符 (+) 进行累加时,您需要在每个组的开头将其重置为缺失。此外,由于您希望组总和与组中的每一行相关联,因此您需要在关联之前计算该总和。双 DOW 循环是一种常见的解决方案——DOW 方法将SETBY 语句放在DO 循环中。在这种情况下,double 表示有一个循环用于计算组的统计数据,而第二个循环用于输出。

      data want;
         * loop over all rows in group to compute the sum;
         var3_sum_over_var1 = .;
         do _n_ = 1 by 1 until (last.var1);
           set have;
           by var1;
           var3_sum_over_var1 + var3;
         end;
      
         * associate var3_sum_over_var1 with each row as it is output;
         do _n_ = 1 to _n_;
           set have;
           OUTPUT;
         end;
      run;
      

      注意:DO 循环开始和停止边界在循环开始时计算一次,并且在循环迭代时不能更改 - 因此do _n_ = 1 to _n_; 可以按需要工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-17
        • 1970-01-01
        • 2018-09-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多