SAS:从行值创建新列,并通过每个唯一的请求 ID 保留这些值

问题描述 投票:0回答:2

我这里有一个示例数据集。 enter image description here

如果工作流程状态包含“批准”,我想通过提取“to_user”值来创建一个名为批准者的新列。它应该与每个唯一的请求号相对应。 我举了一个例子来说明我对新专栏的期望。 我对 sas 很陌生,我做了功能研究,但仍然陷入困境。 谢谢你的帮助!

loops sas sas-macro retain datastep
2个回答
0
投票

您可以使用按组处理来确定(计算)组内的最后一个审批者,然后将其应用于组中的每一行。

示例:

计算组的值并使用 DOW 循环处理将其应用于组中的每一行。

data want;
  do _n_ = 1 by 1 until (last.request_no);
    set have;
    by request_no;
    if find(to_role,'approver','i') then approver = to_user;
  end;
  do _n_ = 1 to _n_;
    set have;
    output;
  end;
run;

0
投票

由于您对 SAS 非常陌生,基于 SQL 的方法可以让您轻松理解这一点。创建一个子集表,当

TO_USER
时,获取
WORKFLOW_STATUS = 'APPROVAL_PINCAB'
的值。这将创建一个如下所示的表:

REQUEST_NO             TO_USER
1401.23.039.1.00005-1  Syahruddin
1402.17.040.6.00023-2  Braindy Soekarno
1402.18.040.6.00072-1  Braindy Soekarno

现在,如果我们通过

REQUEST_NO
在此表上执行左连接,我们将为所有 ID 值填充批准者。

proc sql;
    create table want as
        select t1.*, t2.approver
        from have as t1
        LEFT JOIN
             (select request_no
                   , to_user as approver
              from have
              where workflow_status = 'APPROVAL_PINCAB'
             ) as t2
        ON t1.request_no = t2.request_no
     ;
quit;

另一种方法是通过数据步骤合并。您可以一步完成这一切,但为了清楚起见,这是分多个步骤完成的。

data lookup;
    set have;
    where workflow_status = 'APPROVAL_PINCAB';
    
    keep request_no to_user;
    rename to_user = APPROVER;
run;

proc sort data=lookup;
    by request_no;
run;

proc sort data=have;
    by request_no;
run;

data want;
    merge have
          lookup
    ;
    by request_no;
run;

实现此目的的一种高级方法是通过称为“哈希表”(Kirk Paul Lafler)的东西。这些非常高效,非常适合连接这样的表。我不会详细介绍它的所有细节,因为它在“使用简单键进行搜索和查找”部分的链接论文中进行了解释,但随着您在 SAS 中的进步,您会发现哈希表非常有用。 下面的代码将在内存中存储一个表,该表仅保存

WORKFLOW_STATUS = 'APPROVAL_PINCAB'

的值。当数据步骤一一拉入行时,我们将使用

request_no
方法将
request_no
的值与内存中
Find()
的值进行比较。如果值匹配,我们会将
approver
的值从哈希表拉入数据集。
data want;
    set have;

    /* On the first iteration, define and load a hash table once */
    if(_N_ = 1) then do;
        length approver $50.;

        /* Define the in-memory lookup table */
        dcl hash lookup(dataset: 'have(where=(workflow_status = "APPROVAL_PINCAB")
                                       rename=(to_user = approver)
                                      )'
                       );
            lookup.defineKey('request_no'); * Define the lookup key;
            lookup.defineData('approver');  * Define the data to pull;
        lookup.defineDone();                * Load the table;
   
        call missing(approver); * Needed to prevent uninitialized value notes;
    end;

    /* Compare the set table's value of request_no and compare it 
       to the hash table. If they match, pull the value of approver 
       from the hash table into the new table we're creating. */
    rc = lookup.Find();
    
    drop rc;
run;

© www.soinside.com 2019 - 2024. All rights reserved.