从SAS数据集中提取子数据&应用于不同的数据集

时间:2013-03-27 01:37:32

标签: sas sas-macro

我编写了一个宏来使用proc univariate来计算数据集中变量的自定义分位数(比如dsn1%cust_quants(dsn= , varlist= , quant_list= )。输出是摘要数据集(例如dsn2),如下所示:

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对应于未来的每个目的。有更简单/更清洁的方法吗?

**如果这是足够的背景/示例,请在评论中告诉我。我很乐意更详细地说明为什么我正在做我正在尝试的事情。

1 个答案:

答案 0 :(得分:0)

首先,我假设你在谈论SAS / Base而不是SAS / IML; SAS / IML与R基本相似,并且以相同的方式提供相同类型的操作。

SAS / Base更像是一种数据库语言,而不是矩阵语言(虽然它有一些元素,一些OOP语言的元素,以及一种功能全面的函数式编程语言)。

因此,为了达到同样的目标,你会做一些不同的事情。此外,由于在大型数据表中移动数据的成本,您可以使用多种方法来实现相同的结果;您可以根据需要选择合适的方法。

首先,您通常不应以您建议的方式将数据存储在宏变量中。这是糟糕的编程习惯,效率低下(正如您已经注意到的那样)。存在SAS数据集来存储数据;存在SAS宏变量以帮助简化编程任务并驱动代码。

如上所述在Base SAS中创建数据集“b”是微不足道的:

data b;
set a;
keep v2;
run;

创建一个新的数据集,其行数与A相同,但只有第二列。 KEEP和DROP允许您控制数据集中的哪些列。

但是,除非您计划修改数据,否则此数据集中的要点非常少;毕竟,它包含与A相同的信息,只是更少。因此,例如,如果您想将V2合并到另一个数据集中,而不是创建b,则只需使用A的数据集选项:

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

(注意:我假设某种形式的ID变量组合A和Z.) 此合并将v2列组合到z,在新数据集c中。这相当于垂直连接两个矩阵(尽管直接连接会删除'by id;'要求,在数据库中通常不会这样做,因为订单不能保证符合您的预期。)

如果您打算使用b执行其他操作,则创建和/或使用它的方式取决于该用法。您可以创建format,它是值的映射[即,1 ='Hello'2 ='Goodbye'],因此允许您使用单个编程语句将一个值转换为另一个值。您可以将其加载到哈希表中。您可以将其转置为一行(proc transpose)。提供更多细节,并提供更具体的答案。