2013-03-27 56 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