SAS - 数据步骤等同于Proc SQL

时间:2014-04-16 17:54:01

标签: group-by sas datastep

这个proc sql的数据步骤相当于什么?

proc sql;
create table issues2 as(
select request,
       area,
       sum(issue_count) as issue_count,
       sum(resolved_count) as resolved_count
    from 
        issues1
    group by request, area 
                         );

4 个答案:

答案 0 :(得分:3)

PROC MEANS / SUMMARY更好,但如果相关,则实际数据步骤解决方案如下。基本上您只需将计数器重置为first.<var>上的0并输出last.<var>,其中<var>by组中的最后一个变量。

注意:这假设数据已排序by request area。如果不是,请对其进行排序。

data issues2(rename=(issue_count_sum=issue_count resolved_count_sum=resolved_count) drop=issue_count resolved_count);
 set issues1;
 by request area;
 if first.area then do;
   issue_count_sum=0;
   resolved_count_sum=0;
 end;
 issue_count_sum+issue_count;
 resolved_count_sum+resolved_count;
 if last.area then output;
run;

答案 1 :(得分:2)

您尝试做的功能相当于以下内容:

data _null_;
  set issues1(rename=(issue_count=_issue_count
                      resolved_count=_resolved_count)) end=done;

  if _n_=1 then do;
    declare hash total_issues();
    total_issues.defineKey("request", "area");
    total_issues.defineData("request", "area", "issue_count", "resolved_count");
    total_issues.defineDone();
  end;

  if total_issues.find() ne 0 then do;
    issue_count = _issue_count;
    resolved_count = _resolved_count;
  end;
  else do;
    issue_count + _issue_count;
    resolved_count + _resolved_count;
  end;

  total_issues.replace();

  if done then total_issues.output(dataset: "issues2");
run;

此方法不要求您对数据集进行预排序。我想看看你使用不同方法可以获得什么样的性能,所以我对74M行数据集做了一些测试。我得到了以下运行时间(结果可能会有所不同):

未排序的数据集:

  • Proc SQL - 12.18秒
  • Data使用哈希对象方法(上图) - 26.68秒
  • Proc Means使用class声明(nway) - 5.13秒

排序数据集(36.94秒进行过程排序):

  • Proc SQL - 10.82秒
  • Proc Means使用by声明 - 9.31秒
  • Proc Means使用class声明(nway) - 6.07秒
  • Data使用by语句(我使用了Joe的回答代码) - 8.97秒

正如您所看到的,我不推荐使用上面显示的哈希对象方法的数据步骤,因为它花了两倍于proc sql。

我不确定为什么proc means使用by语句花费的时间比使用proc means语句class更长,但我尝试了一堆不同的语句数据集并看到了运行时的类似差异(我在Linux 64上使用SAS 9.3)。

需要记住的是,这些运行时可能与您的情况完全不同,但我建议使用以下代码进行求和:

proc means data=issues1 noprint nway;
  class request area;
  var issue_count resolved_count;
  output out=issues2(drop=_:) sum=;
run;

答案 2 :(得分:1)

我认为,在数据步骤中完成这一点很麻烦 - 在by变量的每个级别对变量进行求和和重置都可行。哈希对象也可以做到这一点。

也许最简单的非Proc SQL方法是使用Proc Summary: -

proc summary data = issues1 nway missing;
  class request area;
  var issue_count resolved_count;
  output out = issues2 sum(issue_count) = issue_count sum(resolved_count) = resolved_count ;
run;

答案 3 :(得分:1)

这是临时数组方法。这是最简单的&#34;其中,对请求和区域值做出一些假设;如果这些假设是错误的,因为它们通常是真实的数据,它可能不是那么容易。请注意,虽然在下面数据确实正好进行排序,但我并不依赖它进行排序,并且该过程不会从排序中获得任何好处。

data issues1;
do request=1 to 1e5;
  do area = 1 to 7;
    do issueNum = 1 to 1e2;
      issue_count = floor(rand('Uniform')*7);
      resolved_count = floor(rand('Uniform')*issue_count);
      output;
    end;
  end;
end;
run;

data issues2;
set issues1 end=done;
array ra_issue[1100000] _temporary_;
array ra_resolved[1100000] _temporary_;
*array index = request||area, so request 9549 area 6 = 95496.;
ra_issue[input(cats(request,area),best7.)] + issue_count;
ra_resolved[input(cats(request,area),best7.)] + resolved_count;
if done then do;
  do _t = 1 to dim(ra_issue);
    if not missing(ra_issue[_t]) then do;
      request = floor(_t/10);
      area    = mod(_t,10);
      issue_count=ra_issue[_t];
      resolved_count=ra_resolved[_t];
      output;
      keep request area issue_count resolved_count;
    end;
  end;
end;
run;

考虑到我开始使用的简单数据,它与CLASS的PROC MEANS相当。如果你不能从区域和请求的组合中简单地生成一个密钥(例如,如果它们是字符变量),你将不得不存储另一个名称到密钥关系的数组,这将使它成为一个如果有很多组合,那么速度会慢很多(尽管组合相对较少,但并不一定都那么糟糕)。如果由于某种原因你在生产中这样做,我会首先创建一个独特的请求+区域组合表,创建一个格式和一个Informat来来回转换来自一个独特的键(这应该非常快,并给你一个可靠的索引),然后使用那种格式/信息而不是我在这里做的猫/分模数来做到这一点。