2013-03-27 2 views
0

Я написал макрос для использования proc univariate для вычисления пользовательских квантилей для переменных в наборе данных (скажем dsn1) %cust_quants(dsn= , varlist= , quant_list=). Выход резюме набор данных (скажем, dsn2), который выглядит примерно так:Извлечение суб-данных из набора данных SAS и применение к другому набору данных

q_1  q_2.5  q_50  q_80  q_97.5  q_99  var_name 
1  2.5  50  80  97.5  99  ex_var_1_100 
-2  10   25  150  500   20000  ex_var_pos_skew 
-20000 -500  -150  0   10   50  ex_var_neg_skew 

То, что я хотел бы сделать, это использовать сводную набор данных в довершение/пола экстремальных значений в исходном наборе данных. Моя идея - извлечь интересующую колонку (скажем q_99) и поместить ее в вектор макропеременных (скажем q_99_1, q_99_2, ..., q_99_n). Затем я могу сделать что-то вроде следующего:

/* create summary of dsn1 as above example */ 
%cust_quants(dsn= dsn1, varlist= ex_var_1_100 ex_var_pos_skew ex_var_neg_skew, 
      quant_list= 1 2.5 50 80 97.5 99); 

/* cap dsn1 var's at 99th percentile */ 
data dsn1_cap; 
    set dsn1; 

    if ex_var_1_100 > &q_99_1 then ex_var_1_100 = &q_99_1; 
    if ex_var_pos_skew > &q_99_2 then ex_var_pos_skew = &q_99_2; 
    /* don't cap neg skew */ 
run; 

В R, это очень легко сделать это. Можно извлечь суб-данные из фрейма данных с использованием матрицы, такой как индексирование, и назначить эти под-данные объекту. Затем этот второй объект можно будет ссылаться позже. R пример - извлечение b из данных рамы a:

> a <- as.data.frame(cbind(c(1,2,3), c(4,5,6))) 
> print(a) 
    V1 V2 
1 1 4 
2 2 5 
3 3 6 
> a[, 2] 
[1] 4 5 6 
> b <- a[, 2] 
> b[1] 
[1] 4 

Можно ли сделать то же самое в SAS? Я хочу, чтобы иметь возможность назначать столбцы (-ы) под-данных для макро-переменной/массива, чтобы затем я мог использовать макрос/массив во втором шаге данных. Одна мысль proc sql into::

proc sql noprint; 
    select v2 into :v2_macro separated by " " 
    from a; 
run; 

Однако это создает одну строковую переменную, когда то, что я действительно хочу это вектор переменных (или массив - нет векторов в SAS). Еще одна мысль, чтобы добавить %scan (при условии, что это внутри макро):

proc sql noprint; 
    select v2 into :v2_macro separated by " " 
    from a; 
run; 

%let i = 1; 
%do %until(%scan(&v2_macro, &i) = ""); 
    %let var_&i = %scan(&v2_macro, &i); 
    %let &i = %eval(&i + 1); 
%end; 

Это кажется неэффективным и занимает много кода. Это также требует, чтобы программист помнил, какой var_&i соответствует каждой будущей цели. Есть ли более простой/чистый способ сделать это?

** Пожалуйста, дайте мне знать в комментариях, если этого достаточно фона/примера. Я рад дать более полное описание того, почему я делаю то, что я пытаюсь при необходимости.

ответ

0

Прежде всего, я предполагаю, что вы говорите о SAS/Base не SAS/IML; SAS/IML по существу похож на R и имеет тот же вид операций, доступных таким же образом.

SAS/Base больше похож на язык базы данных, чем на язык матриц (хотя он имеет некоторые элементы как для одного, так и для некоторых элементов языка ООП, а также является полнофункциональным функциональным языком программирования).

В результате вы делаете что-то по-другому, чтобы достичь той же цели. Кроме того, из-за стоимости перемещения данных в большой таблице данных вам предоставляется несколько методов для достижения того же результата; вы можете выбрать подходящий метод для требуемой ситуации.

Во-первых, вы не должны хранить данные в макропеременной таким образом, как вы предлагаете. Это плохая практика программирования, и она неэффективна (как вы уже заметили). Наборы данных SAS существуют для хранения данных; Существуют макро переменные SAS, которые упрощают задачи программирования и приводят код.

Создание набора данных «б», как указано выше тривиально в Base SAS:

data b; 
set a; 
keep v2; 
run; 

Это создает новый набор данных с теми же строками, как А, но только второй столбец. KEEP и DROP позволяют вам контролировать, какие столбцы находятся в наборе данных.

Однако в этом наборе данных будет очень мало смысла, если только вы не планируете изменять данные; в конце концов, он содержит ту же информацию, что и A, всего лишь меньше. Так, например, если вы хотите, чтобы объединить V2 в другой набор данные, а не создавать б, вы могли бы просто использовать вариант набора данных с A:

data c; 
merge z a(keep=v2); 
by id; 
run; 

(Примечание: Я предполагаю ID переменный некоторую форму, чтобы объединить и Z.) Это объединение объединяет столбец v2 в z в новом наборе данных, c. Это эквивалентно вертикальной конкатенации двух матриц (хотя прямое конкатенация удаляет требование «по id», в базах данных, которые обычно не выполняются, поскольку порядок не гарантируется тем, что вы ожидаете).

Если вы планируете использовать b, чтобы сделать что-то еще, то, как вы его создаете и/или используете, зависит от этого использования. Вы можете создать format, который является отображением значений [т.е. 1 = 'Hello' 2 = 'Goodbye'] и, таким образом, позволяет преобразовать одно значение в другое с помощью одного оператора программирования. Вы можете загрузить его в хеш-таблицу. Вы можете перенести его в ряд (proc transpose). Поставьте более подробную информацию и получите более конкретный ответ.

+0

спасибо. Я уточню сообщение для более подробного описания того, что я делаю. –

Смежные вопросы