簡體   English   中英

SAS - 相當於 Proc SQL 的數據步驟

[英]SAS - Data Step equivalent of Proc SQL

與此 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 
                         );

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;

您正在嘗試做的功能等效如下:

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 排序):

  • Proc SQL - 10.82 秒
  • Proc Means使用by語句 - 9.31 秒
  • Proc Means使用class語句 (nway) - 6.07 秒
  • 使用by語句的Data步驟(我使用了 Joe 回答中的代碼)- 8.97 秒

如您所見,我不建議將數據步驟與上面顯示的哈希對象方法一起使用,因為它花費的時間是 proc sql 的兩倍。

我不確定為什么proc means使用by語句比使用class語句的proc means花費更長的時間,但是我在一堆不同的數據集上嘗試了這個,並看到了運行時的類似差異(我在 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;

我認為,完全在數據步驟中進行操作很尷尬 - 在by變量的每個級別對變量進行求和和重置會起作用。 散列對象也可能起作用。

也許最簡單的非 Proc SQL 方法是使用 Proc 摘要:-

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;

這是臨時數組方法。 這是其中“最簡單的”,對請求和面積值做了一些假設; 如果這些假設是錯誤的,因為它們通常存在於真實數據中,那么事情可能不會這么簡單。 請注意,雖然在下面的數據確實被排序,但我不依賴於它被排序並且該過程不會從它被排序中獲得任何優勢。

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 相當。 如果您不能從 area 和 request 的組合中輕松生成一個鍵(例如,如果它們是字符變量),您將不得不存儲另一個名稱到鍵關系的數組,這會使其速度變慢如果有很多組合(盡管如果組合相對較少,也不一定都那么糟糕)。 如果由於某種原因您在生產中這樣做,我將首先創建一個唯一請求+區域組合的表,創建一個 Format 和一個 Informat 以從唯一鍵來回轉換(這應該非常快,並為您提供可靠的index),然后使用該格式/信息而不是我在這里所做的貓/除法模數來執行此操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM