我编写了一个宏来使用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
对应于未来的每个目的。有更简单/更清洁的方法吗?
**如果这是足够的背景/示例,请在评论中告诉我。我很乐意更详细地说明为什么我正在做我正在尝试的事情。
答案 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
)。提供更多细节,并提供更具体的答案。