2015-11-13 5 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? Либо на этапе DATA, либо на этапе 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 в несколько наблюдений с значениями отдельных пар, разделенных на NAME и VALUE переменных.

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

Это работает для сценария с одиночной записью. Если я не ошибаюсь, Transpose не будет работать, если есть несколько записей, которые нужно передать my_string из шага данных. ??? –

+0

Вам нужна переменная или переменные, чтобы однозначно идентифицировать исходную строку, которую вы можете передать PROC TRANSPOSE в инструкции BY. – 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, мы воспользовались этим и поэтому код SAS, который был запущен из fileref tempcode с помощью %include должен выглядеть следующим образом:

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; 

Надежда все это помогает (и работает!)

С уважением, Амир.