2013-03-27 57 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例子 - 從數據幀a提取b

> 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 /基本沒有SAS/IML; SAS/IML與R基本相似,並且具有相同的操作方式。

SAS /基地更類似於比矩陣語言數據庫語言(儘管既有的一些元件,和一個OOP語言的一些元件,以及作爲一個全功能的功能的編程語言)。

其結果是,你爲了達到同樣的目標做的事情有所不同。此外,由於在大型數據表中移動數據的成本,您可以使用多種方法來實現相同的結果;您可以根據需要選擇合適的方法。

首先,你一般不應將數據存儲在你建議的方式的宏變量。這是不好的編程習慣,效率低下(正如你已經注意到的)。存在SAS數據集來存儲數據; SAS宏變量的存在有助於簡化您的編程任務並驅動代碼。

創建數據集「B」如上述在鹼SAS瑣碎:

data b; 
set a; 
keep v2; 
run; 

即創建具有相同的行爲A的新數據集,但只有第二列中。 KEEP和DROP允許您控制數據集中的哪些列。

但是,除非您打算修改數據,否則這個數據集中的點很少。畢竟,它包含的信息與A相同,只是更少。因此,舉例來說,如果你想合併V2到另一個數據集,而不是創建B,你可以只使用一個數據集的選項:

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

(注:我預設了某種形式的ID變量爲結合和Z.) 該合併將v2列結合到z上,在新數據集c中。這相當於垂直連接兩個矩陣(儘管直接連接會刪除'by id;'的要求,在通常不這樣做的數據庫中,因爲順序不保證是您期望的)。

如果您計劃使用b來做其他事情,您如何創建和/或使用它取決於該用法。你可以創建一個format,它是一個值的映射[即,1 ='Hello'2 ='Goodbye'],因此可以使用單個編程語句將一個值轉換爲另一個值。您可以將其加載到散列表中。你可以將它轉換成一行(proc transpose)。提供更多的細節和更具體的答案。

+0

謝謝。我會更新這篇文章,詳細說明我正在做什麼。 – 2013-03-27 12:59:45