2015-11-13 66 views
3

我有一列包含許多從XML解析器分析的標誌。數據如下所示:SAS - 使用另一列中的值動態創建列名稱

USERKEYED=Y;VALMATCH=N;DEVICEVERIFIED=N;EXCEPTION=N;USERREGISTRD=N;ASSOCIATE=Y;EXTERNAL=N;GROSSGIVEN=Y;UMAPPED=N; 

我必須創建一個包含所有這些列名稱的表來捕獲標誌。如:

USERKEYED VALMATCH DEVICEVERIFIED EXCEPTION USERREGISTRD ASSOCIATE EXTERNAL GROSSGIVEN UMAPPED 
Y N N N N Y N Y N 
Y N N N N Y Y Y N 
Y N N Y N Y N Y N 

如何在SAS中動態捕獲值?無論是在數據步驟還是PROC步驟?

在此先感謝。

+0

在數據中讀入第一個變量作爲變量,第二個變量作爲值讀取。然後轉置數據。 – Reeza

+0

數據集中或文本文件中的字符變量中的字符串是否需要讀取?如果它是在一個文本文件中,那麼也許你可以使用命名輸入樣式來閱讀。但是你需要知道變量名才能寫入輸入語句。 – Tom

+0

謝謝你的回覆。現在我嘗試了字符串函數,它工作正常。儘管它正在工作,但是對於我來說代碼看起來並不令人滿意,如果將更多標誌添加到列中,它需要更改代碼。 –

回答

2

讓我們從您的示例輸出數據開始。

data expect ; 
    id+1; 
    length USERKEYED VALMATCH DEVICEVERIFIED EXCEPTION 
     USERREGISTRD ASSOCIATE EXTERNAL GROSSGIVEN UMAPPED $1 ; 
    input USERKEYED -- UMAPPED; 
cards4; 
Y N N N N Y N Y N 
Y N N N N Y Y Y N 
Y N N Y N Y N Y N 
;;;; 

現在我們可以重新創建你的榜樣輸入數據:

data have ; 
    do until (last.id); 
    set expect ; 
    by id ; 
    array flag _character_; 
    length string $200 ; 
    do _n_=1 to dim(flag); 
     string=catx(';',string,catx('=',vname(flag(_n_)),flag(_n_))); 
    end; 
    end; 
    keep id string; 
run; 

這將是這樣的:

USERKEYED=Y;VALMATCH=N;DEVICEVERIFIED=N;EXCEPTION=N;USERREGISTRD=N;ASSOCIATE=Y;EXTERNAL=N;GROSSGIVEN=Y;UMAPPED=N 
USERKEYED=Y;VALMATCH=N;DEVICEVERIFIED=N;EXCEPTION=N;USERREGISTRD=N;ASSOCIATE=Y;EXTERNAL=Y;GROSSGIVEN=Y;UMAPPED=N 
USERKEYED=Y;VALMATCH=N;DEVICEVERIFIED=N;EXCEPTION=Y;USERREGISTRD=N;ASSOCIATE=Y;EXTERNAL=N;GROSSGIVEN=Y;UMAPPED=N 

所以處理這一點,我們需要從變量解析出對STRING轉化爲多個觀察值,其中個體對的值分爲NAMEVALUE變量。

data middle ; 
    set have ; 
    do _n_=1 by 1 while(_n_=1 or scan(string,_n_,';')^=' '); 
    length name $32 ; 
    name = scan(scan(string,_n_,';'),1,'='); 
    value = scan(scan(string,_n_,';'),2,'='); 
    output; 
    end; 
    keep id name value ; 
run; 

然後我們可以使用PROC TRANSPOSE將這些觀察值轉換成變量。

proc transpose data=middle out=want (drop=_name_) ; 
    by id; 
    id name ; 
    var value ; 
run; 
0
DATA <MY_DATASET>; 
SET INPUT_DATASET; 
USERKEYED = substr(input_column, find(input_column, 'USERKEYED=')+10,1); 
VALMATCH = substr(input_column, find(input_column, 'VALMATCH=')+9,1); 
DEVICEVERIFIED = substr(input_column, find(input_column, 'DEVICEVERIFIED=')+15,1); 
EXCEPTION = substr(input_column, find(input_column, 'EXCEPTION=')+10,1); 
USERREGISTRD = substr(input_column, find(input_column, 'USERREGISTRD=')+13,1); 
ASSOCIATE = substr(input_column, find(input_column, 'ASSOCIATE=')+10,1); EXTERNAL = substr(input_column, find(input_column, 'EXTERNAL=')+9,1); 
GROSSGIVEN = substr(input_column, find(input_column, 'GROSSGIVEN=')+11,1); 
UMAPPED = substr(input_column, find(input_column, UMAPPED=')+8,1); 
run; 
1

您擁有的數據是一系列名稱/值對,使用;作爲分隔符。我們可以在一個時間提取每個名稱/值對中的一個,然後解析那些入值:

data tmp; 
    length my_string next_pair name value $200; 
    my_string = "USERKEYED=Y;VALMATCH=N;DEVICEVERIFIED=N;EXCEPTION=N;USERREGISTRD=N;ASSOCIATE=Y;EXTERNAL=N;GROSSGIVEN=Y;UMAPPED=N;"; 
    cnt = 1; 
    next_pair = scan(my_string,cnt,";"); 
    do while (next_pair ne ""); 
    name = scan(next_pair,1,"="); 
    value = scan(next_pair,2,"="); 
    output; 
    cnt = cnt + 1; 
    next_pair = scan(my_string,cnt,";"); 
    end; 
    keep name value; 
run; 

得到:

name    value 
=================== ===== 
USERKEYED   Y 
VALMATCH   N 
DEVICEVERIFIED  N 
EXCEPTION   N 
USERREGISTRD  N 
ASSOCIATE   Y 
EXTERNAL   N 
GROSSGIVEN   Y 
UMAPPED    N 

然後,我們可以調換,以便該名稱用於該數據列名:

proc transpose data=tmp out=want(drop=_name_); 
    id name; 
    var value; 
run; 

它給你所需的表。

+0

這適用於單記錄場景。如果我沒有錯,如果有多個記錄需要從數據步驟傳遞給my_string,則Transpose將不起作用。 ??? –

+0

您需要一個或多個變量來唯一標識可以在BY語句中傳遞給PROC TRANSPOSE的原始行。 – Tom

+0

@NagaVemprala如果你更新你的數據,我會更新我的代碼=) –

0

我的答案本質上是第一塊代碼,其餘的只是解釋,一個替代方案和一個不錯的提示。

根據您所提供的答案,輸入數據已經是一個SAS數據集,因此可以讀取創建的SAS代碼的文件,然後可以使用%include運行等proc transpose要求:

filename tempcode '<path><file-name.txt>'; /* set this up yourself */ 

/* write out SAS code to the fileref tempcode */ 
data _null_; 
    file tempcode; 
    set have; 
    if _n_=1 then 
    put 'Y="Y"; N="N"; drop Y N;'; 
    put input_column; 
    put 'output;'; 
run; 

/* %include the code to create the desired output */ 
data want; 
    %include tempcode; 
run; 

由於輸入數據已經幾乎看起來像SAS賦值語句,我們採取的這種優勢,因此已經從fileref tempcode使用%include運行SAS代碼應該是這樣的:

Y="Y"; N="N"; drop Y N; 
USERKEYED=Y;VALMATCH=N;DEVICEVERIFIED=N;EXCEPTION=N;USERREGISTRD=N;ASSOCIATE=Y;EXTERNAL=N;GROSSGIVEN=Y;UMAPPED=N; 
output; 
USERKEYED=Y;VALMATCH=N;DEVICEVERIFIED=N;EXCEPTION=N;USERREGISTRD=N;ASSOCIATE=Y;EXTERNAL=Y;GROSSGIVEN=Y;UMAPPED=N; 
output; 
USERKEYED=Y;VALMATCH=N;DEVICEVERIFIED=N;EXCEPTION=Y;USERREGISTRD=N;ASSOCIATE=Y;EXTERNAL=N;GROSSGIVEN=Y;UMAPPED=N; 
output; 

作爲替代方案,fileref tempcode可以包含所有用於數據的步驟「data want;」的代碼:

/* write out entire SAS data step code to the fileref tempcode */ 
data _null_; 
    file tempcode; 
    set have end=lastrec; 
    if _n_=1 then 
    put 'data want;' 
     /'Y="Y"; N="N"; drop Y N;'; 

    put input_column; 
    put 'output;'; 

    if lastrec then 
    put 'run;'; 
run; 

%include tempcode; /* no need for surrounding SAS code */ 

作爲尖端,看到在日誌可以使用下面的變化由%include正在處理的代碼:

%include tempcode/source2; 

希望這一切都有助於(和工作!)

問候, 阿米爾。